bzoj 1031 [JSOI2007]字符加密Cipher
求出来后缀数组的rank就行了,不会可以去看集训队论文。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<vector> 6 using namespace std; 7 char c[200005]; 8 int rank[200005],sa[200005]; 9 int n; 10 int a[200005],b[200005],wb[200005],wv[200005],gs[200005]; 11 bool cmp(int *x,int a,int b,int l) 12 { 13 return x[a]==x[b]&&x[a+l]==x[b+l]; 14 } 15 void da(int *x,int *sa,int n,int m) 16 { 17 int i,j,p,*y=wb; 18 for(i=0;i<m;i++)gs[i]=0; 19 for(i=0;i<n;i++)gs[x[i]]++; 20 for(i=1;i<m;i++)gs[i]+=gs[i-1]; 21 for(i=n-1;~i;i--)sa[--gs[x[i]]]=i; 22 for(j=1,p=1;p<n;j<<=1,m=p) 23 { 24 for(i=n-j,p=0;i<n;i++)y[p++]=i; 25 for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j; 26 for(i=0;i<n;i++)wv[i]=x[y[i]]; 27 for(i=0;i<m;i++)gs[i]=0; 28 for(i=0;i<n;i++)gs[wv[i]]++; 29 for(i=1;i<m;i++)gs[i]+=gs[i-1]; 30 for(i=n-1;~i;i--)sa[--gs[wv[i]]]=y[i]; 31 swap(x,y);x[sa[0]]=0;p=1; 32 for(i=1;i<n;i++)x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; 33 } 34 } 35 int main() 36 { 37 scanf("%s",c); 38 n=strlen(c); 39 for(int i=n;i<2*n;i++)c[i]=c[i-n]; 40 for(int i=0;i<n<<1;i++)rank[i]=c[i]; 41 da(rank,sa,n*2+1,256); 42 for(int i=1;i<=n*2;i++) 43 { 44 if(sa[i]+n-1<n*2-1)putchar(c[sa[i]+n-1]); 45 } 46 return 0; 47 }