倍增求后缀数组
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("
");
53 for(int i=0;i<len;i++){
54 printf("%d",sa[i]);
55 }
56 printf("
");
57 for(int i=0;i<len;i++){
58 printf("%d",height[i]);
59 }
60 return 0;
61 }