poj2774 Long Long Message
【题意】
两个串的最长公共连续子串
【分析】
直接连到一起,中间加上间隔符,求height之后,二分答案判断在是否属于两个串
【代码】
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; const int maxn=2e5+5; int n; char a[maxn],s[maxn],b[maxn]; int h[maxn],maxi,id[maxn]; int sa[maxn],rk[maxn],oldrk[maxn],cnt[maxn],fz[maxn]; bool cmp(int x,int y,int w) { return oldrk[x]==oldrk[y] && oldrk[x+w]==oldrk[y+w]; } void calcsa() { int m=233; for(int i=0;i<=m;i++) cnt[i]=0; for(int i=1;i<=n;i++) cnt[rk[i]=a[i]]++; for(int i=1;i<=m;i++) cnt[i]+=cnt[i-1]; for(int i=n;i>=1;i--) sa[cnt[rk[i]]--]=i; int i,p; for(int w=1;;w<<=1,m=p) { for(p=0,i=n;i>n-w;i--) id[++p]=i; for(i=1;i<=n;i++) if(sa[i]>w) id[++p]=sa[i]-w; for(i=0;i<=m;i++) cnt[i]=0; for(i=1;i<=n;i++) cnt[fz[i]=rk[id[i]]]++; for(i=1;i<=m;i++) cnt[i]+=cnt[i-1]; for(i=n;i>=1;i--) sa[cnt[fz[i]]--]=id[i]; for(i=1;i<=n;i++) oldrk[i]=rk[i]; for(p=0,i=1;i<=n;i++) rk[sa[i]]=cmp(sa[i],sa[i-1],w)?p:++p; if(p==n) { for(i=1;i<=n;i++) sa[rk[i]]=i; break; } } } void calch() { int i,k=0; for(i=1;i<=n;i++) { if(k) k--; while(a[i+k]==a[sa[rk[i]-1]+k]) k++; h[rk[i]]=k; } } int len1; int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); scanf("%s",s+1); scanf("%s",b+1); len1=strlen(s+1); for(int i=1;i<=len1;i++) a[i]=s[i]; n+=len1; s[++n]=1; int len2=strlen(b+1); for(int i=1;i<=len2;i++) a[i+n]=b[i]; n+=len2; calcsa(); calch(); int ans=0; for(int i=2;i<n;i++) { if(0<=sa[i] && sa[i]<=len1 && len1+1<sa[i-1]) ans=max(ans,h[i]); if(0<=sa[i-1] && sa[i-1]<=len1 && len1+1<sa[i]) ans=max(ans,h[i]); } printf("%d",ans); return 0; }