P3435 [POI2006]OKR-Periods of Words
题目链接
KMP算法。
一开始主要是题意没搞懂,搞懂了就好写了。题目大意就是:给定一个字符串,让你求这个字符串的每一个前驱的proper前驱的长度总和,proper前驱的意思就是某个字符串(x)的一个不为自己的前驱,复制两遍后拼接起来的字符串为(y),使(x)是(y)的前驱。
(使用了洛谷 @Orion545dalao的图)
图中黑色的是字符串(x),蓝色的就是我们要找的proper前驱。利用(next)数组的性质,我们可以使两段绿色的部分相同,这样当蓝色的部分复制两遍拼接起来后得到的字符串(y),(x)肯定是(y)的前驱。所以我们现在找到一个不为0的最小的(next)就好了,让(ans += len_x - next)。
注意要使用一个优化:(next[x])等于绿色部分长度。不然会TLE。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
int n, j, nxt[N];
long long ans;
char ch[N];
int main() {
cin >> n; cin >> ch + 1;
for(int i = 2;i <= n; i++) {
while(j && ch[j + 1] != ch[i]) j = nxt[j];
j += (ch[j + 1] == ch[i]); nxt[i] = j;
}
for(int i = 1;i <= n; i++) {
j = i;
while(nxt[j]) j = nxt[j];
if(nxt[i]) nxt[i] = j; //优化
ans += i - j;
}
printf("%lld", ans);
return 0;
}