【模板】后缀数组模板

这几天在学后缀数组(补题补到绝望决定来学点新东西),等我再学的明白一点,并且有时间心情好的时候(遥遥无期,而且估计写了也没人看),就来写一篇后缀数组的知识点博客~

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <iostream>
 5 
 6 using namespace std;
 7 const int maxn=10000;
 8 char s[maxn];
 9 int sa[maxn],t[maxn],t1[maxn],c[maxn];
10 int n;
11 void build_sa(int m){
12     int *x=t,*y=t1;
13     for(int i=0;i<m;i++)c[i]=0;
14     for(int i=0;i<n;i++)c[x[i]=s[i]]++;
15     for(int i=1;i<m;i++)c[i]+=c[i-1];
16     for(int i=n-1;i>=0;i--)sa[--c[x[i]]]=i;
17 
18     for(int k=1;k<=n;k<<=1){
19         int p=0;
20         for(int i=n-k;i<n;i++)y[p++]=i;
21         for(int i=0;i<n;i++)if(sa[i]>=k)y[p++]=sa[i]-k;
22         for(int i=0;i<m;i++)c[i]=0;
23         for(int i=0;i<n;i++)c[x[y[i]]]++;//这里为啥是这样?一会结合基数排序想一下
24         for(int i=1;i<m;i++)c[i]+=c[i-1];
25         for(int i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];
26         swap(x,y);
27         p=1,x[sa[0]]=0;
28         for(int i=1;i<n;i++)
29           x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p-1:p++;
30         if(p>=n)break;
31         m=p;
32     }
33 }
34 
35 int m;
36 int cmp_suffix(char* pattern,int p){
37     return strncmp(pattern,s+sa[p],m);
38 }
39 int find(char *P){
40     m=strlen(P);
41     if(cmp_suffix(P,0)<0)return -1;
42     if(cmp_suffix(P,n-1)>0)return -1;
43     int L=0,R=n-1;
44     while(R>=L){
45         int M=L+(R-L)/2;
46         int res=cmp_suffix(P,M);
47         if(!res)return M;
48         if(res<0)R=M-1;
49         else L=M+1;
50     }
51 }
52 int rank[maxn],height[maxn];//rank数组是后缀i的排名,height数组是sa[i-1]和sa[i]的最长公共前缀
53 //后缀j和k的LCP长度等于RMQ(height,rank[j]+1,rank[k])。
54 void getHeight(){
55     int k=0;
56     for(int i=0;i<n;i++)rank[sa[i]]=i;
57     for(int i=0;i<n;i++){
58         if(k)k--;
59         int j=sa[rank[i]-1];
60         while(s[i+k]==s[j+k])k++;
61         height[rank[i]]=k;
62     }
63 }
64 
65 int d[maxn][30];
66 void RMQ_init(){
67     for(int i=0;i<n;i++){
68         d[i][0]=height[i];
69     }
70     for(int i=1;(1<<i)<=n;i++){
71         for(int j=0;(1<<i)+j<n;j++){
72             d[j][i]=min(d[j][i-1],d[j+(1<<(i-1))][i-1]);
73         }
74     }
75 }
76 
77 int LCP(int k,int j){
78     if(rank[k]>rank[j])
79         swap(k,j);
80     int L=rank[k]+1,R=rank[j];
81     int i=0;
82     while((1<<(i+1))<=R-L+1)i++;
83     return min(d[L][i],d[R-(1<<i)+1][i]);
84 }
85 
86 int main(){
87     scanf("%s",s);
88     n=strlen(s);
89     build_sa('a'+27);
90     getHeight();
91     RMQ_init();
92     int j,k;
93     while(scanf("%d%d",&j,&k)!=EOF&&(j||k)){
94         printf("%d\n",LCP(j,k));
95     }
96 return 0;
97 }

猜你喜欢

转载自www.cnblogs.com/LQLlulu/p/9440281.html
今日推荐