3648. 【GDOI2014】beyond (Standard IO)
Time Limits: 1000 ms Memory Limits: 262144 KB
思路:
先做两次扩展KMP,求出 a的后缀匹配b的最长长度exA[i]和b的后缀匹配a的最长长度exB[i]
枚举长度L
在KMP中加些处理求出以A[I]为结尾的后缀中与B匹配的最长长度j,再判断j和它的next中最大的j+exB[j+1](KMP+DP预处理)如果大于L,则L为可行解
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<cstring> using namespace std; int s1[2000222],s2[2000222],a[2000222],b[2000222]; int exA[2000222],exB[2000222],next[2000222]; int dp[2000222],dp2[2000222]; int m,n,i,t,xzq,l; char c; void Read(int *s) { m=0; while(c=getchar(),c<'a'||c>'z'); s[++m]=c; while(c=getchar(),c>='a'&&c<='z')s[++m]=c; } void Exkmp() { int len,l,k,i; memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); len=0; k=0; for(i=2;i<=n;i++){ if(len<i){ l=0; while(s1[i+l]==s1[1+l]&&i+l<=n)l++; a[i]=l; } else{ if(a[i-k+1]<len-i+1)a[i]=a[i-k+1]; else{ l=len-i+1; while(s1[i+l]==s1[1+l]&&i+l<=n)l++; a[i]=l; } } if(i+a[i]-1>len){ len=i+a[i]-1; k=i; } } len=0; k=0; for(i=1;i<=n;i++){ if(len<i){ l=0; while(s2[i+l]==s1[1+l]&&i+l<=n){ if(l+1>dp[i+l])dp[i+l]=l+1; l++; } b[i]=l; } else{ if(a[i-k+1]<len-i+1)b[i]=a[i-k+1]; else{ l=len-i+1; while(s2[i+l]==s1[1+l]&&i+l<=n){ if(l+1>dp[i+l])dp[i+l]=l+1; l++; } b[i]=l; } } if(i+b[i]-1>len){ len=i+b[i]-1; k=i; } } } void Kmp() { int i,j,x; memset(next,0,sizeof(next)); x=0; for(i=2;i<=n;i++){ while(x!=0&&s1[i]!=s1[x+1])x=next[x]; if(s1[i]==s1[x+1])x++; next[i]=x; if(dp2[x]>dp2[i])dp2[i]=dp2[x]; } } int main() { scanf("%d",&n); Read(s1); Read(s2); Exkmp(); for(i=1;i<=n;i++)exB[i]=b[i]; for(i=1;i<=n;i++){ t=s1[i]; s1[i]=s2[i]; s2[i]=t; } memset(dp,0,sizeof(dp)); Exkmp(); for(i=1;i<=n;i++)exA[i]=b[i]; for(i=1;i<=n;i++)dp2[i]=i+exB[i+1]; Kmp(); for(i=1;i<=n;i++){ l=dp[i]; if(dp2[l]>=i)xzq=i; } printf("%d ",xzq); }