POJ 2774 Long Long Message
思路
把两个串接在一起,求后缀数组和height,扫一遍即可。
代码
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<iostream> 5 6 using namespace std; 7 8 const int N = 200100; 9 char s[N]; 10 int c[N],t1[N],t2[N],sa[N],height[N],rnk[N]; 11 //sa[i] 排名为i的是谁 -下标 12 //rnk[i] i的排名 -名次 13 //height[i] 排名为i的后缀与排名为i-1的后缀的最长公共前缀长度 14 int m = 130,n; 15 16 void get_sa() { 17 int *x = t1,*y = t2,p,i; 18 for (i=0; i<m; ++i) c[i] = 0; 19 for (i=0; i<n; ++i) x[i] = s[i],c[x[i]]++; 20 for (i=1; i<m; ++i) c[i] += c[i-1]; 21 for (i=n-1; i>=0; --i) sa[--c[x[i]]] = i; 22 for (int k=1; k<=n; k<<=1) { 23 p = 0; 24 for (i=n-k; i<n; ++i) y[p++] = i; 25 for (i=0; i<n; ++i) if (sa[i]>=k) y[p++] = sa[i]-k; 26 for (i=1; i<m; ++i) c[i] = 0; 27 for (i=0; i<n; ++i) c[ x[y[i]] ]++; 28 for (i=1; i<m; ++i) c[i] += c[i-1]; 29 for (i=n-1; i>=0; --i) sa[--c[ x[y[i]] ]] = y[i]; 30 swap(x,y); 31 p = 1; 32 x[sa[0]] = 0; 33 for (i=0; i<n; ++i) 34 x[sa[i]] = y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++; 35 if (p >= n) break; 36 m = p; 37 } 38 } 39 void get_height() { 40 for (int i=0; i<n; ++i) rnk[sa[i]] = i; 41 int k = 0; 42 height[0] = 0; 43 for (int i=0; i<n; ++i) { 44 if (!rnk[i]) continue; 45 if (k) k--; 46 int j = sa[rnk[i]-1]; 47 while (i+k<n && j+k<n && s[i+k]==s[j+k]) k++; 48 height[rnk[i]] = k; 49 } 50 } 51 52 int main() { 53 scanf("%s",s); 54 int n1 = strlen(s); 55 scanf("%s",s+n1); 56 int n2 = strlen(s+n1); 57 n = n1 + n2; 58 get_sa(); 59 get_height(); 60 int ans = 0; 61 for (int i=1; i<n; ++i) { 62 int mn = min(sa[i],sa[i-1]); 63 int mx = max(sa[i],sa[i-1]); 64 if (mn < n1 && mx >= n1) ans = max(ans,height[i]); 65 } 66 printf("%d",ans); 67 return 0; 68 }