BZOJ1031-[JSOI2007]字符加密Cipher
题意:
题解:
这道题约等于后缀数组的模板题了.把字符串复制一份接在原字符串的尾部,形成一个新字符串.对这个字符串进行后缀排序,前一半的排名就是按题意排序后的结果.
第一次写后缀数组,有很多细节要注意,也调了好久,代码里面基本上是一行一个for循环,差点被搞炸.
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=400000; char s[N+10]; int n,ch_sz=200,sa[N+10],rk[N+10],c[N+10],sa2[N+10],p; void sort_suffix(){ for(int i=1;i<=n;++i) ++c[rk[i]=s[i]]; for(int i=1;i<=ch_sz;++i) c[i]+=c[i-1]; for(int i=n;i>=1;--i) sa[c[rk[i]]--]=i; for(int i=1;i<=n;i*=2){ p=0; for(int j=n-i+1;j<=n;++j) sa2[++p]=j; for(int j=1;j<=n;++j) if(sa[j]>i) sa2[++p]=sa[j]-i; for(int j=1;j<=ch_sz;++j) c[j]=0; for(int j=1;j<=n;++j) ++c[rk[sa2[j]]]; for(int j=1;j<=ch_sz;++j) c[j]+=c[j-1]; for(int j=n;j>=1;--j) sa[c[rk[sa2[j]]]--]=sa2[j]; swap(rk,sa2); rk[sa[1]]=ch_sz=1; for(int j=2;j<=n;++j) rk[sa[j]]=sa2[sa[j]]==sa2[sa[j-1]]&&sa2[sa[j]+i]==sa2[sa[j-1]+i]?ch_sz:++ch_sz; if(ch_sz==n) break; } } int main(){ scanf("%s",s+1); n=strlen(s+1); for(int i=n+1;i<=n*2;++i) s[i]=s[i-n]; n<<=1; sort_suffix(); for(int i=1;i<=n;++i) if(sa[i]<=n/2) printf("%c",s[sa[i]+n/2-1]); return 0; }