链接:
#include <stdio.h>
int main()
{
puts("转载请注明出处[vmurder]谢谢");
puts("网址:blog.csdn.net/vmurder/article/details/45768837");
}
题解:
首先我们如果设原串为串[ 1,n ]
然后 fi 表示串[ i+1,n?i ]中最长的串长使得串[ i+1,i+fi ]==串[n?i?fi+1,n?i]
这时存在一个性质 fi?1<=fi+2
然后就可以线性递推啦!
证明:
现在让我们来反证一下这个性质:
下图有四种情况,f[i]为红色, f[i-1]为全图。
显然无论何时,f[i-1]对应图去掉两侧点,皆可以保证是一个f[i]。
所以fi?1<=fi+2
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 1001000
#define mod 1000000009
#define base 1000000007
using namespace std;
int n,ans;
char s[N];
long long sum[N],hash[N],pw[N];
long long gethash(int l,int r)
{return (hash[r]+mod-hash[l-1]*pw[r-l+1]%mod)%mod;}
int main()
{
freopen("test.in","r",stdin);
int i,j,k;
scanf("%d",&n);
for(pw[0]=i=1;i<=n;i++)pw[i]=(long long)pw[i-1]*base%mod;
scanf("%s",s+1);
for(i=1;i<=n;i++)
{
hash[i]=(hash[i-1]*base%mod+s[i])%mod;
sum[i]=sum[i-1]+s[i];
}
for(i=n>>1,j=0;~i;i--)
if(sum[i]==sum[n]-sum[n-i])
if(gethash(1,i)==gethash(n-i+1,n))
for(j=min(n/2-i,j+2);j>=0;j--)
if(sum[i+j]-sum[i]==sum[n-i]-sum[n-i-j])
if(gethash(i+1,i+j)==gethash(n-i-j+1,n-i))
{ans=max(ans,i+j);break;}
printf("%d\n",ans);
return 0;
}
时间: 2024-11-08 13:55:50