【模板】后缀数组

【模板】后缀数组

 注意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("
");
61     for(int i=1;i<n;i++) printf("%d ",height[i]);
62     return 0;
63 }