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