题目链接:hdu_1403_Longest Common Substring
题意:
给你两个字符串,然你找最长的公共子串
题解:
后缀数组的经典应用,要找两个字符串的公共子串,那么就相当于找两个串的后缀的最长公共前缀,我们将两个字符串拼接在一起,中间插一个特殊字符
然后我们考虑height数组,height数组存的是排i和i-1的最长前缀,如果sa[i]和sa[i-1]在特殊字符的两边,那么这个height[i]记录的就是这两个串的最长
子串,然后扫一遍height数组更新一下答案就行了
1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;++i) 3 using namespace std; 4 5 namespace suffixarray{ 6 #define FN(n) for(int i=0;i<n;i++) 7 const int N =2E5+7;//字符串长度 8 int rnk[N],sa[N],height[N],c[N];char s[N]; 9 void getsa(int n,int m,int *x=rnk,int *y=height){ 10 FN(m)c[i]=0;FN(n)c[x[i]=s[i]]++;FN(m)c[i+1]+=c[i]; 11 for(int i=n-1;i>=0;i--)sa[--c[x[i]]]=i; 12 for(int k=1,p;p=0,k<=n;k=p>=n?N:k<<1,m=p){ 13 for(int i=n-k;i<n;i++)y[p++]=i; 14 FN(n)if(sa[i]>=k)y[p++]=sa[i]-k; 15 FN(m)c[i]=0;FN(n)c[x[y[i]]]++;FN(m)c[i+1]+=c[i]; 16 for(int i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i]; 17 swap(x,y),p=1,x[sa[0]]=0; 18 for(int i=1;i<n;i++) 19 x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++; 20 } 21 FN(n)rnk[sa[i]]=i; 22 for(int i=0,j,k=0;i<n-1;height[rnk[i++]]=k) 23 for(k=k?k-1:k,j=sa[rnk[i]-1];s[i+k]==s[j+k];k++); 24 } 25 } 26 using namespace suffixarray; 27 int main(){ 28 while(~scanf("%s",s)) 29 { 30 int len=strlen(s),sz; 31 s[len]=‘$‘; 32 scanf("%s",s+len+1); 33 sz=strlen(s),getsa(sz+1,128); 34 int ans=0; 35 F(i,1,sz)if(ans<height[i]&&(sa[i]-len)*(sa[i-1]-len)<0)ans=height[i]; 36 printf("%d\n",ans); 37 } 38 return 0; 39 }
时间: 2024-10-21 13:13:22