这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
2020-2021:teams:legal_string:jxm2001:other:错题集_3 [2020/08/27 20:16] jxm2001 |
2020-2021:teams:legal_string:jxm2001:other:错题集_3 [2020/08/31 18:12] (当前版本) jxm2001 |
||
---|---|---|---|
行 541: | 行 541: | ||
} | } | ||
enter(1LL*ans*ans%Mod); | enter(1LL*ans*ans%Mod); | ||
+ | return 0; | ||
+ | } | ||
+ | </code> | ||
+ | </hidden> | ||
+ | |||
+ | ===== 7、B-Suffix Array ===== | ||
+ | |||
+ | [[https://ac.nowcoder.com/acm/contest/5666/A|链接]] | ||
+ | |||
+ | ==== 题意 ==== | ||
+ | |||
+ | 给出一个字符串,定义一个字符串 $S$ 对应序列 $B$,其中 $b_i=\min_{j\lt i,s_j=s_i} (i-j)$,如果不存在 $j$,$b_i=0$。 | ||
+ | |||
+ | 求序列 $B$ 后缀排序后的结果。 | ||
+ | |||
+ | ==== 题解 ==== | ||
+ | |||
+ | 构造 $c_i=\min_{j\gt i,s_j=s_i}(j-i)$,如果不存在 $j$,$b_i=n$。特别的,$c_{n+1}$ 为 $c$ 的结束符且 $c_{n+1}=n+1$。 | ||
+ | |||
+ | 有结论将 $B$ 序列后缀排序结果翻转后与 $C[1,n+1]$ 后缀排序前 $n$ 项相同。 | ||
+ | |||
+ | <hidden 查看代码> | ||
+ | <code cpp> | ||
+ | #include <cstdio> | ||
+ | #include <algorithm> | ||
+ | #define _for(i,a,b) for(int i=(a);i<(b);++i) | ||
+ | #define _rep(i,a,b) for(int i=(a);i<=(b);++i) | ||
+ | #define mem(a,b) memset(a,b,sizeof(a)) | ||
+ | using namespace std; | ||
+ | typedef long long LL; | ||
+ | const int MAXN=1e5+5; | ||
+ | namespace SA{ | ||
+ | int sa[MAXN],x[MAXN],y[MAXN],c[MAXN]; | ||
+ | void get_sa(int *s,int n,int m){ | ||
+ | _rep(i,0,m)c[i]=0; | ||
+ | _rep(i,1,n)c[x[i]=s[i]]++; | ||
+ | _rep(i,1,m)c[i]+=c[i-1]; | ||
+ | for(int i=n;i;i--)sa[c[x[i]]--]=i; | ||
+ | for(int k=1;k<n;k<<=1){ | ||
+ | int pos=0; | ||
+ | _rep(i,n-k+1,n)y[++pos]=i; | ||
+ | _rep(i,1,n)if(sa[i]>k)y[++pos]=sa[i]-k; | ||
+ | _rep(i,0,m)c[i]=0; | ||
+ | _rep(i,1,n)c[x[i]]++; | ||
+ | _rep(i,1,m)c[i]+=c[i-1]; | ||
+ | for(int i=n;i;i--)sa[c[x[y[i]]]--]=y[i],y[i]=0; | ||
+ | _rep(i,1,n)swap(x[i],y[i]); | ||
+ | pos=0,y[n+1]=0; | ||
+ | _rep(i,1,n)x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])?pos:++pos; | ||
+ | if(pos==n)break; | ||
+ | m=pos; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | char buf[MAXN]; | ||
+ | int a[MAXN],last[2]; | ||
+ | int main() | ||
+ | { | ||
+ | int n; | ||
+ | while(~scanf("%d%s",&n,buf+1)){ | ||
+ | last[0]=last[1]=0; | ||
+ | for(int i=n;i;i--){ | ||
+ | int c=buf[i]-'a'; | ||
+ | if(last[c])a[i]=last[c]-i; | ||
+ | else a[i]=n; | ||
+ | last[c]=i; | ||
+ | } | ||
+ | a[n+1]=n+1; | ||
+ | SA::get_sa(a,n+1,n+1); | ||
+ | for(int i=n;i;i--) | ||
+ | printf("%d ",SA::sa[i]); | ||
+ | puts(""); | ||
+ | } | ||
return 0; | return 0; | ||
} | } | ||
</code> | </code> | ||
</hidden> | </hidden> |