后缀数组笔记
倍增求后缀数组
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cmath> 5 using namespace std; 6 int rank[10001],sa[10001],height[10001],buc[10001],x[10001],y[10001],n,len; 7 char st[10001]; 8 bool cmp(int *s,int n,int m,int x){ 9 return s[n]==s[m]&&s[n+x]==s[m+x]; 10 } 11 void initsa(int n,int m){ 12 memset(buc,0,sizeof(buc)); 13 for(int i=0;i<n;i++)buc[x[i]=st[i]]++; 14 for(int i=1;i<m;i++)buc[i]+=buc[i-1]; 15 for(int i=len-1;i>=0;i--)sa[--buc[x[i]]]=i; 16 for(int j=1,p=1;p<n;j*=2,m=p){ 17 p=0; 18 for(int i=n-j;i<n;i++)y[p++]=i; 19 for(int i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j; 20 memset(buc,0,sizeof(buc)); 21 for(int i=0;i<n;i++)buc[x[y[i]]]++; 22 for(int i=1;i<m;i++)buc[i]+=buc[i-1]; 23 for(int i=n-1;i>=0;i--)sa[--buc[x[y[i]]]]=y[i]; 24 swap(x,y); 25 int i; 26 for(p=1,x[sa[0]]=0,i=1;i<n;i++){ 27 x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; 28 } 29 } 30 } 31 void initra(){ 32 for(int i=0;i<len;i++)rank[sa[i]]=i; 33 } 34 void initheight(){ 35 int j,k=0; 36 for(int i=0;i<len;i++){ 37 if(k)k--; 38 j=sa[rank[i]-1]; 39 while(st[i+k]==st[j+k])k++; 40 height[rank[i]]=k; 41 } 42 } 43 int main(){ 44 scanf("%s",st); 45 len=(int)strlen(st); 46 initsa(len,128); 47 initra(); 48 initheight(); 49 for(int i=0;i<len;i++){ 50 printf("%d",rank[i]); 51 } 52 printf("\n"); 53 for(int i=0;i<len;i++){ 54 printf("%d",sa[i]); 55 } 56 printf("\n"); 57 for(int i=0;i<len;i++){ 58 printf("%d",height[i]); 59 } 60 return 0; 61 }