1 /****************************************************************** 2 题目: Long Long Message(poj 2774) 3 链接: http://poj.org/problem?id=2774 4 题意: 给两个字符串,找最长的公共子串 5 算法: 后缀数组 6 算法思想: 后缀数组就是套模板求先应得数组,这题用到了两个数组,分 7 别是sa[],height[];sa[i]表示所有后缀按字典数排序后以s[i] 8 开始的后缀排在第i位。height[i]表示字典数为i和i-1后缀的 9 的最长串的前缀。 10 *******************************************************************/ 11 #include<cstdio> 12 #include<cstring> 13 #include<algorithm> 14 using namespace std; 15 16 const int mx=200100; 17 char st[mx]; 18 int s[mx],sa[mx],t[mx],t2[mx],c[mx],n; 19 int rank[mx],height[mx]; 20 21 void build_sa(int m) 22 { 23 int i,*x=t,*y=t2; 24 for (i=0;i<m;i++) c[i]=0; 25 for (i=0;i<n;i++) c[x[i]=s[i]]++; 26 for (i=1;i<m;i++) c[i]+=c[i-1]; 27 for (i=n-1;i>=0;i--) sa[--c[x[i]]]=i; 28 for (int k=1;k<=n;k<<=1) 29 { 30 int p=0; 31 for (i=n-k;i<n;i++) y[p++]=i; 32 for (i=0;i<n;i++) if (sa[i]>=k) y[p++]=sa[i]-k; 33 for (i=0;i<m;i++) c[i]=0; 34 for (i=0;i<n;i++) c[x[y[i]]]++; 35 for (i=1;i<m;i++) c[i]+=c[i-1]; 36 for (i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i]; 37 swap(x,y); 38 p=1; 39 x[sa[0]]=0; 40 for (i=1;i<n;i++) 41 x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++; 42 if (p>=n) break; 43 m=p; 44 } 45 } 46 47 void getHeight() 48 { 49 int i,j,k=0; 50 for (i=0;i<n;i++) rank[sa[i]]=i; 51 for (i=0;i<n;i++) 52 { 53 if (k) k--; 54 int j=sa[rank[i]-1]; 55 while (s[i+k]==s[j+k]) k++; 56 height[rank[i]]=k; 57 } 58 } 59 60 int main() 61 { 62 n=0; 63 int l1,l2; 64 scanf("%s",st); 65 l1=strlen(st); 66 for (int i=0;i<l1;i++) s[n++]=st[i]-'a'+1; 67 s[n++]=28; 68 scanf("%s",st); 69 l2=strlen(st); 70 for (int i=0;i<l2;i++) s[n++]=st[i]-'a'+1; 71 s[n++]=0; 72 build_sa(30); 73 getHeight(); 74 int maxx=0; 75 for (int i=2;i<n;i++) 76 { 77 if (maxx<height[i]) 78 { 79 if (sa[i]>=0&&sa[i]<l1&&sa[i-1]>l1) 80 maxx=height[i]; 81 if (sa[i-1]>=0&&sa[i-1]<l1&&sa[i]>l1) 82 maxx=height[i]; 83 } 84 } 85 printf("%d\n",maxx); 86 return 0; 87 }