正题
luogu
CF961F
题目大意
给你一个字符串T,对于k=1~n/2,找到最长的串s,满足s是T左右各删除k个字符构成的字串t的前缀后缀(不能是整个字符串)
解题思路
不难发现,k的答案左右各删一个字符必定能得到k+1的答案(不一定是最大),那么k的答案必定小于等于k+1的答案+2
那么可以从中间向两边计算答案,每移一位就+2,然后一直-2,直到找到基数前缀后缀
时间复杂度 O(n)O(n)O(n)
code
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define mod 1000000007
#define N 1001000
using namespace std;
int n,now,ans[N];
ll hs[N],pw[N];
char s[N];
ll get(int x,int len)
{int y=x+len-1;return (hs[y]-hs[x-1]*pw[len]%mod+mod)%mod;
}
int main()
{scanf("%d%s",&n,s+1);pw[0]=1;for(int i=1;i<=n;++i)(hs[i]=hs[i-1]*131%mod+s[i])%mod,pw[i]=pw[i-1]*131%mod;if(n&1)ans[(n+1)/2]=-1;now=-1;for(int i=n/2;i>0;--i){int j=n-i+1;now+=2;while(now>-1&&get(i,now)!=get(j-now+1,now))now-=2;ans[i]=now;}for(int i=1;i<=(n+1)/2;++i)printf("%d ",ans[i]);return 0;
}