[POI2006]OKR-Periods of Words
Posted wyxwyx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[POI2006]OKR-Periods of Words相关的知识,希望对你有一定的参考价值。
Description
Luogu3435
对一个字符串(A),定义其周期(Q)为,(Q)为(A)的前缀((Q!=A))且(A)为(QQ)的前缀((A)可以等于(QQ))。求一个字符串的所有前缀的最长周期的长度之和。
Solution
首先观察周期的定义,可以发现,一旦该字符串有一个前缀等于该字符串的一个后缀,那么这个字符串就是有周期的,与前后缀有关的那就是KMP了。而要求周期最长,就是要求该前缀最短,转化问题之后就可以用KMP解决了。但是,sb的我竟然在KMP的过程中xjb乱跳,直接就跳到最短的了,可是这样会挂啊!考虑这样的一个字符串abacabac
,如果在KMP里就处理答案的话就会影响next
数组的求解,所以要在KMP之后求答案。
哦对了,求答案的时候可以记忆化一下。
Code
#include <cstdio>
typedef long long LL;
const int N = 1e6 + 10;
char s[N];
int nxt[N];
LL ans;
int n;
int main() {
scanf("%d", &n);
scanf("%s", s+1);
nxt[0] = -1;
for (int i = 1; i <= n; ++i) {
int t = nxt[i-1];
while (t != -1 && s[t+1] != s[i]) t = nxt[t];
/* 这里不能有这句话啊!!!!!!!!!!!!!!!
if (t != -1) while (nxt[t] != -1 && s[nxt[t] + 1] == s[i]) t = nxt[t];
*/ nxt[i] = t + 1;
}
for (int i = 1; i <= n; ++i) {
int t = nxt[i];
while (nxt[t] > 0) t = nxt[t];
if (nxt[i]) nxt[i] = t; // 记忆化一下
if (t) ans += i - t;
}
printf("%lld
", ans);
return 0;
}
以上是关于[POI2006]OKR-Periods of Words的主要内容,如果未能解决你的问题,请参考以下文章
P3435 [POI2006]OKR-Periods of Words
OKR-Periods of Words「POI 2006」
bzoj 1511: [POI2006]OKR-Periods of Wordskmp