[POI2006]Periods of Words
题目大意:
给定一个长度为$n(n\leq10^6)$的字符串$S$,定义一个串$S$的最大周期为一个不为$S$的字符串$Q$,满足$Q$为$S$的前缀且$S$为$QQ$的前缀。求字符串$S$的每一个前缀的最大周期长度之和。
思路:
KMP+DP。
不难发现串$S$去掉前缀串$Q$后,剩下的串是$Q$的最短非空前缀。首先用KMP算法求出$next$数组。然而$next$求出来是最长,要让它变成最短,需要用DP的思想,向前找到最初的非0$next$对应的长度$f_i$,最后求$\sum(i-f[i])$即可。
1 #include<cstdio> 2 typedef long long int64; 3 const int N=1e6+1; 4 char s[N]; 5 int n,next[N],f[N]; 6 int main() { 7 scanf("%d%s",&n,s); 8 for(register int i=0,j=next[0]=-1;i<n;next[++i]=++j) { 9 while(~j&&s[i]!=s[j]) j=next[j]; 10 } 11 int64 ans=0; 12 for(register int i=1;i<=n;i++) { 13 f[i]=next[i]?f[next[i]]:i; 14 ans+=i-f[i]; 15 } 16 printf("%lld\n",ans); 17 return 0; 18 }