HDU 1403 Longest Common Substring(最長公共前綴)
阿新 • • 發佈:2017-09-22
+= 前綴 pri substr 排序 turn void 數組 swap
http://acm.hdu.edu.cn/showproblem.php?pid=1403
題意:
給出兩個字符串,求最長公共子串的長度。
思路:
剛開始學後綴數組,確實感覺很難,但是這東西很強大,所以必須要學會它,推薦羅穗騫大牛的論文。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #include<stack> 7 #include<queue> 8#include<cmath> 9 #include<map> 10 #include<set> 11 using namespace std; 12 typedef long long ll; 13 typedef pair<int,int> pll; 14 const int INF = 0x3f3f3f3f; 15 const int maxn=200000+5; 16 17 char s[maxn],s1[maxn]; 18 int sa[maxn],t[maxn],t2[maxn],c[maxn],n; 19 int Rank[maxn],height[maxn];20 21 void build_sa(int m) 22 { 23 int *x=t,*y=t2; 24 //基數排序 25 for(int i=0;i<m;i++) c[i]=0; 26 for(int i=0;i<n;i++) c[x[i]=s[i]]++; 27 for(int i=1;i<m;i++) c[i]+=c[i-1]; 28 for(int i=n-1;i>=0;i--) sa[--c[x[i]]]=i; 29 for(int k=1;k<=n;k<<=1) 30 { 31 int p=0; 32 //直接利用sa數組排序第二關鍵字 33 for(int i=n-k;i<n;i++) y[p++]=i; 34 for(int i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k; 35 //基數排序第一關鍵字 36 for(int i=0;i<m;i++) c[i]=0; 37 for(int i=0;i<n;i++) c[x[y[i]]]++; 38 for(int i=1;i<m;i++) c[i]+=c[i-1]; 39 for(int i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i]; 40 //根據sa和y計算新的x數組 41 swap(x,y); 42 p=1; 43 x[sa[0]]=0; 44 for(int i=1;i<n;i++) 45 x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++; 46 if(p>=n) 47 break; 48 m=p; //下次基數排序的最大值 49 } 50 } 51 52 void getHeight() 53 { 54 int i,j,k=0; 55 for(i=1;i<=n;i++) Rank[sa[i]]=i; 56 for(i=0;i<n;i++) 57 { 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 main() 66 { 67 //freopen("in.txt","r",stdin); 68 while(~scanf("%s",s)) 69 { 70 int len = strlen(s); 71 s[len]=‘0‘; 72 scanf("%s",s+len+1); 73 n=strlen(s); 74 build_sa(128); 75 getHeight(); 76 int ans=0; 77 for(int i=1;i<n;i++) 78 { 79 if(height[i]>ans) 80 { 81 if((sa[i]>len && sa[i-1]<len) || (sa[i]<len && sa[i-1]>len)) 82 ans=height[i]; 83 } 84 } 85 printf("%d\n",ans); 86 } 87 return 0; 88 }
HDU 1403 Longest Common Substring(最長公共前綴)