POJ2774-Long Long Message-后缀数组
后缀数组处理最长公共子串问题。
将两个串接在一起,计算height的最大值。同时要保证sa[i]和sa[i-1]在不同的串当中。
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 5 using namespace std; 6 7 const int maxn = 2e5+10; 8 char s[maxn]; 9 int sa[maxn],t[maxn],t2[maxn],c[maxn]; 10 int rank[maxn],height[maxn]; 11 12 void build(int n,int m) 13 { 14 int i,j,p,*x = t, *y = t2; 15 16 for(i=0;i<m;i++)c[i]=0; 17 for(i=0;i<n;i++)c[x[i]=s[i]]++; 18 for(i=1;i<m;i++)c[i]+=c[i-1]; 19 for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i; 20 for(j=1;j<=n;j<<=1) 21 { 22 p=0; 23 for(i=n-j;i<n;i++)y[p++]=i; 24 for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j; 25 for(i=0;i<m;i++)c[i]=0; 26 for(i=0;i<n;i++)c[x[y[i]]]++; 27 for(i=1;i<m;i++)c[i]+=c[i-1]; 28 for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i]; 29 swap(x,y); 30 p=1;x[sa[0]]=0; 31 for(i=1;i<n;i++) 32 x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++; 33 if(p>=n)break; 34 m=p; 35 } 36 n--; 37 int k = 0; 38 for(int i=0;i<=n;i++) rank[sa[i] ] = i; 39 for(int i=0;i<n;i++) 40 { 41 if(k) k--; 42 int j = sa[rank[i]-1]; 43 while(s[i+k]==s[j+k]) k++; 44 height[rank[i] ] = k; 45 } 46 } 47 48 char line_1[maxn],line_2[maxn]; 49 50 bool check(int a,int b,int len) 51 { 52 if(a > b) swap(a,b); 53 if(a < len && b > len) 54 { 55 return true; 56 } 57 return false; 58 } 59 60 int main() 61 { 62 while(~scanf("%s%s",line_1,line_2)) 63 { 64 int len1 = strlen(line_1); 65 int len2 = strlen(line_2); 66 int n = len1+len2+1; 67 for(int i=0;i<len1;i++) s[i] = line_1[i]; 68 s[len1] = 1; 69 for(int i=0;i<len2;i++) s[len1+1+i] = line_2[i]; 70 s[len1+len2+1] = 0; 71 72 //printf("%s\n",s); 73 build(n+1,128); 74 int ans = 0; 75 for(int i=1;i<n;i++) 76 { 77 if(check(sa[i],sa[i-1],len1)) 78 ans = max(ans,height[i]); 79 } 80 printf("%d\n",ans); 81 } 82 }