洛谷 P3435 [POI2006]OKR-Periods of Words

题目传送门

解题思路:

这道题题面比较乱,先说一下这道题要求什么:

对于一个字符串,求它及它的所有前缀的一个答案串的长度之和,答案串就是对于一个字符串,找到一个它的一个前缀,这个前缀后面在复制一遍,得到一个新串,这个新串包含原来那个字符串,而且这个前缀要求找符合要求的最长的.

这道题要求的答案串很显然就是整个字符串减去最短公共前后缀(不为0),若无公共前后缀,那么就无周期.

那么如何求最短公共前后缀呢?暴力的做法就是递归next[i],next[next[i]]...

而我们用记忆化,每找一个最短公共前后缀,就把next[i]更新,下次直接调用next[i]就找到答案了.

AC代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 
 4 using namespace std;
 5 
 6 int n,kmp[1000001],j;
 7 long long ans;
 8 string l,p;
 9 
10 int main() {
11     scanf("%d",&n);
12     cin >> p;
13     l = " " + p;
14     kmp[1] = 0;
15     for(int i = 2;i <= n; i++) {
16         while(j != 0 && l[i] != l[j+1]) j = kmp[j];
17         if(l[i] == l[j+1]) j++;
18         kmp[i] = j;
19     }
20     for(int i = 2,u = i;i <= n; i++,u = i) {
21         while(kmp[u]) u = kmp[u];
22         if(kmp[i]) kmp[i] = u;
23         ans += i - u; 
24     }
25     printf("%lld",ans);
26     return 0;
27 }
原文地址:https://www.cnblogs.com/lipeiyi520/p/12364441.html