標籤:des style class blog code http
3648. 【GDOI2014】beyond (Standard IO)Time Limits: 1000 ms Memory Limits: 262144 KB Description
Input第一行:包含一個整數N。
第二行:包含一個長度為N的字串,字串中只包含小寫字母。
第三行:包含一個長度為N的字串,字串中只包含小寫字母。Output輸出答案只包含一個數字L,表示圓環最大可能有的格子數。 Sample Input輸入1:
5
abcdx
cdabz
輸入2:
4
abcd
cdabSample Output輸出1:
4
輸出2:
4 Data Constraint對於20% 的資料,1 <= N <= 5,000
對於50% 的資料,1 <= N <= 600,000
對於100% 的資料,1 <= N <= 2,000,000
思路:
先做兩次擴充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\n",xzq);}