【模板】后缀数组
注意x,y数组的意义
x[i]表示编号为i的后缀的第一关键字
y[i]表示第二关键字排名为i的后缀编号
h[i]表示编号为i的后缀与其前一名的最大公共前缀
height[i]表示排名为i的后缀与其前一名的最大公共前缀
h[i]>=h[i-1]-1
代码打的比较丑,有时间重新打一遍
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=2000010; 4 int n,s[N]; 5 int m,x[N],y[N],sa[N],cnt[N],rank[N]; 6 int h[N],height[N]; 7 char ss[N]; 8 void build_sa(){ 9 for(int i=0;i<n;i++) cnt[x[i]]++; 10 for(int i=1;i<m;i++) cnt[i]+=cnt[i-1]; 11 for(int i=n-1;~i;i--) sa[--cnt[x[i]]]=i; 12 for(int i=0;i<m;i++) cnt[i]=0; 13 for(int k=1;k<=n;k<<=1){ 14 int num=0; 15 for(int i=n-1;i>=n-k;i--) y[num++]=i; 16 for(int i=0;i<n;i++) if(sa[i]>=k) y[num++]=sa[i]-k; 17 for(int i=0;i<n;i++) cnt[x[i]]++; 18 for(int i=1;i<m;i++) cnt[i]+=cnt[i-1]; 19 for(int i=n-1;~i;i--) sa[--cnt[x[y[i]]]]=y[i]; 20 for(int i=0;i<m;i++) cnt[i]=0; 21 swap(x,y); 22 num=0; 23 x[sa[0]]=num; 24 for(int i=1;i<n;i++){ 25 if(y[sa[i]]!=y[sa[i-1]]||y[sa[i-1]+k]!=y[sa[i]+k]) num++; 26 x[sa[i]]=num; 27 } 28 num++; 29 if(num>=n) break; 30 m=num; 31 } 32 for(int i=0;i<n;i++) rank[sa[i]]=i; 33 return; 34 } 35 void build_height(){ 36 int t=0; 37 for(int i=0;i<n;i++){ 38 if(t) t--; 39 if(!rank[i]) h[i]=0; 40 else{ 41 while(s[i+t]==s[sa[rank[i]-1]+t]) t++; 42 h[i]=t; 43 } 44 height[rank[i]]=h[i]; 45 } 46 return; 47 } 48 int main(){ 49 scanf("%s",ss); 50 n=strlen(ss); 51 for(int i=0;i<n;i++){ 52 if(ss[i]>='0'&&ss[i]<='9') s[i]=ss[i]-'0'; 53 else if(ss[i]>='A'&&ss[i]<='Z') s[i]=ss[i]-'A'+10; 54 else s[i]=ss[i]-'a'+36; 55 x[i]=s[i]; 56 } 57 m=62; 58 build_sa();build_height(); 59 for(int i=0;i<n;i++) printf("%d ",sa[i]+1); 60 printf("\n"); 61 for(int i=1;i<n;i++) printf("%d ",height[i]); 62 return 0; 63 }