[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 }

 

posted @ 2018-03-13 20:49  skylee03  阅读(99)  评论(0编辑  收藏  举报