题目描述
You are given a string s s s consisting of n n n lowercase Latin letters.Let's denote k k k -substring of s s s as a string subsk=sksk+1..sn+1−k subs_{k}=s_{k}s_{k+1}..s_{n+1-k} subsk=sksk+1..sn+1−k . Obviously, subs1=s subs_{1}=s subs1=s , and there are exactly such substrings.
Let's call some string t t t an odd proper suprefix of a string T T T iff the following conditions are met:
- ∣T∣>∣t∣ |T|>|t| ∣T∣>∣t∣ ;
- ∣t∣ |t| ∣t∣ is an odd number;
- t t t is simultaneously a prefix and a suffix of T T T .
For evey k k k -substring () of s s s you have to calculate the maximum length of its odd proper suprefix.
输入输出格式
输入格式:The first line contains one integer n n n (2<=n<=106) (2<=n<=10^{6}) (2<=n<=106) — the length s s s .
The second line contains the string s s s consisting of n n n lowercase Latin letters.
输出格式:Print integers. i i i -th of them should be equal to maximum length of an odd proper suprefix of i i i -substring of s s s (or −1 -1 −1 , if there is no such string that is an odd proper suprefix of i i i -substring).
输入输出样例
15
bcabcabcabcabca
9 7 5 3 1 -1 -1 -1
24
abaaabaaaabaaabaaaabaaab
15 13 11 9 7 5 3 1 1 -1 -1 1
19
cabcabbcabcabbcabca
5 3 1 -1 -1 1 1 -1 -1 -1
说明
The answer for first sample test is folowing:
- 1-substring: bcabcabcabcabca
- 2-substring: cabcabcabcabc
- 3-substring: abcabcabcab
- 4-substring: bcabcabca
- 5-substring: cabcabc
- 6-substring: abcab
- 7-substring: bca
- 8-substring: c
Solution:
集训第二天,昨天HRZ学长讲的NOI2016我只搞出了一道(话说我是真的菜)。
今天的字符串专题讲了下本题,然后思路非常巧妙:字符串hash+类似kmp的方法。
首先字符串hash就随便讲下,直接将每位当作$k$进制数取模就好了,一般$k=131$然后模数搞个质数,当然为了防止出错,可以搞多模数。
然后我们发现本题的一个性质,那就是$ans[1]-2leq ans[2]$,这个很显然啊,那么我们移项后得到$ans[1]leq ans[2]+2$。
不难想到我们可以从最中间的情况开始考虑,然后往前枚举,对于当前答案$ans[cnt]$,可以肯定的是$ans[cnt]leq ans[cnt+1]+2$,所以每次答案最多增加一个$2$,若不行就回退,最多减少$n$个$2$(注意不能小于$-1$)。学长说这有点像KMP的算法复杂度证明,显然有一共最多增加$frac{n}{2}$个$2$,最多减少$frac{n}{2}$个$2$,所以复杂度是$O(n)$的,具体实现时,只需要取出该长度的两个字符串hash值,比较一下直到相等就好了。有点玄学,但是还是能理解吧。
代码:
#include<bits/stdc++.h> #define il inline #define ll long long #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++) #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--) using namespace std; const ll N=2000005,M=131,mod1=998244353,mod2=19260817; ll f[N],p[N],sum[N],ans[N>>1],cnt; int n; char s[N]; il void solve(){ sum[0]=1; For(i,1,n) f[i]=(f[i-1]*M+s[i])%mod1,sum[i]=(sum[i-1]*M)%mod1; int l,r; cnt=n+1>>1; if(n&1)ans[cnt]=-1,l=r=n+1>>1; else { l=n>>1,r=l+1; s[l]==s[r]?ans[cnt]=1:ans[cnt]=-1; } ll p,q; while(cnt--){ ans[cnt]=ans[cnt+1]+2; if(!cnt)break; l--,r++; p=-1,q=1; while(ans[cnt]!=-1){ p=(f[l+ans[cnt]-1]-f[l-1]*sum[ans[cnt]]%mod1+mod1)%mod1; q=(f[r]-f[r-ans[cnt]]*sum[ans[cnt]]%mod1+mod1)%mod1; if(p==q) break; ans[cnt]-=2; } } For(i,1,(n+1)>>1) printf("%lld ",ans[i]); } int main(){ scanf("%d%s",&n,s+1); solve(); return 0; }