题目描述:
给定两个字符串A和B,求最长公共子串。
算法标签:后缀数组
以下代码:
#include<bits/stdc++.h> #define il inline using namespace std; const int N=2e5+5;char s[N],a[N],b[N]; int n,l1,l2,sa[N],rk[N],height[N],c[N],x[N],y[N],ans; il void getsa(){ int m=128; for(int i=1;i<=n;i++)c[x[i]=s[i]]++; for(int i=2;i<=m;i++)c[i]+=c[i-1]; for(int i=n;i;i--)sa[c[x[i]]--]=i; for(int k=1;k<=n;k<<=1){ int num=0; for(int i=n-k+1;i<=n;i++)y[++num]=i; for(int i=1;i<=n;i++)if(sa[i]-k>0)y[++num]=sa[i]-k; for(int i=1;i<=m;i++)c[i]=0; for(int i=1;i<=n;i++)c[x[i]]++; for(int i=2;i<=m;i++)c[i]+=c[i-1]; for(int i=n;i;i--)sa[c[x[y[i]]]--]=y[i],y[i]=0; swap(x,y);x[sa[1]]=1;num=1; for(int i=2;i<=n;i++) x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])?num:++num; if(num==n)break;m=num; } for(int i=1;i<=n;i++)rk[sa[i]]=i; } il void geth(){ int k=0; for(int i=1;i<=n;i++){ if(rk[i]==1)continue; if(k)k--;int j=sa[rk[i]-1]; while(j+k<=n&&i+k<=n&&s[i+k]==s[j+k])k++; height[rk[i]]=k; } } int main() { scanf(" %s",a+1);scanf(" %s",b+1);l1=strlen(a+1);l2=strlen(b+1); for(int i=1;i<=l1;i++)s[i]=a[i];n=l1;s[++n]='#'; for(int i=1;i<=l2;i++)s[++n]=b[i];s[++n]='$'; getsa();geth(); for(int i=2;i<=n;i++){ if((sa[i-1]<=l1&&sa[i]<=l1)||(sa[i-1]>l1+1&&sa[i]>l1+1))continue; ans=max(ans,height[i]); } printf("%d ",ans); return 0; }