bzoj1031: [JSOI2007]字符加密Cipher(后缀数组)
1031: [JSOI2007]字符加密Cipher
题目:传送门
正解:
后缀数组裸题。。。
刚开始看的时候可能觉得一个个排序很麻烦,其实在后面接多一个相同的字符串之后再跑一边sa就ok
因为对于每一个组成顺序不同的字符串来说,其实长度都是一样的,这就保证了他们在这个长度的范围内就可以比较出大小。
所以我们所做的预处理是没有影响的。
输出的时候再稍微判断一下就AC了...有点水
手撸模版:
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 #define N 1100000 7 using namespace std; 8 int Rank[N],Rsort[N],sa[N],y[N],wr[N]; 9 char s[N]; 10 int a[N]; 11 int len,n; 12 bool cmp(int k1,int k2,int ln){return wr[k1]==wr[k2] && wr[k1+ln]==wr[k2+ln];} 13 void get_sa(int n,int m) 14 { 15 memcpy(Rank,a,sizeof(Rank)); 16 17 memset(Rsort,0,sizeof(Rsort)); 18 for(int i=1;i<=n;i++)Rsort[Rank[i]]++; 19 for(int i=1;i<=m;i++)Rsort[i]+=Rsort[i-1]; 20 for(int i=n;i>=1;i--)sa[Rsort[Rank[i]]--]=i; 21 22 int ln=1,k,p=0; 23 while(p<n) 24 { 25 k=0; 26 for(int i=n-ln+1;i<=n;i++)y[++k]=i; 27 for(int i=1;i<=n;i++)if(sa[i]>ln)y[++k]=sa[i]-ln; 28 29 for(int i=1;i<=n;i++)wr[i]=Rank[y[i]]; 30 31 memset(Rsort,0,sizeof(Rsort)); 32 for(int i=1;i<=n;i++)Rsort[wr[i]]++; 33 for(int i=1;i<=m;i++)Rsort[i]+=Rsort[i-1]; 34 for(int i=n;i>=1;i--)sa[Rsort[wr[i]]--]=y[i]; 35 36 for(int i=1;i<=n;i++)wr[i]=Rank[i]; 37 p=1;Rank[sa[1]]=1; 38 for(int i=2;i<=n;i++) 39 { 40 if(!cmp(sa[i],sa[i-1],ln))p++; 41 Rank[sa[i]]=p; 42 } 43 m=p;ln*=2; 44 } 45 } 46 int main() 47 { 48 scanf("%s",s+1);len=strlen(s+1); 49 n=len*2;int j=0; 50 for(int i=len+1;i<=n;i++)s[i]=s[++j]; 51 for(int i=1;i<=n;i++)a[i]=s[i]; 52 get_sa(n,1000); 53 for(int i=1;i<=n;i++) 54 { 55 if(sa[i]>len)continue; 56 else 57 { 58 printf("%c",a[sa[i]+len-1]); 59 } 60 } 61 printf("\n"); 62 return 0; 63 }