[POI2006]OKR-Periods of Words 题解

妙啊+1.

一般题目会让你求最小周期,这个让你求最大周期,咋办?
就是不停的跳$next$,直到不能跳了为止。

红色部分为不能继续跳的$next$部分。不难通过一一对应及$border$的性质证明。

加个记忆化,这个题就做完了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/**
* @Author: Mingyu Li
* @Date: 2019-03-16T23:00:02+08:00
* @Email: class11limingyu@126.com
* @Filename: P3435.cpp
* @Last modified by: Mingyu Li
* @Last modified time: 2019-03-16T23:10:37+08:00
*/

#include <bits/stdc++.h>
#define Go(i , x , y) for(register int i = x; i <= y; i++)
#define God(i , y , x) for(register int i = y; i >= x; i--)
typedef long long LL;
template < typename T > void sc(T& t) {
char c = getchar(); T x = 1; t = 0; while(!isdigit(c)) {if(c == '-') x = -1; c = getchar();}
while(isdigit(c)) t = t * 10 + c - '0' , c = getchar();t *= x;
}
template < typename T , typename... Args > void sc(T& t , Args&... args) {sc(t); sc(args...);}

const int N = 1000000 + 10;
int next[N] , n;
char c[N];
int main() {
sc(n);scanf("%s" , (c + 1));
next[1] = 0;
Go(i , 2 , n) {
int j = next[i-1];
while(j && c[i] != c[j + 1]) j = next[j];
if(c[i] == c[j+1]) next[i] = j+1;
else next[i] = 0;
}
LL ans = 0;
Go(i , 2 , n) {
int j = i;
while(next[j]) j = next[j];
if(next[i]) next[i] = j;
ans += 1ll * (i - j);
}

std::cout << ans << "\n";
return 0;
}
# KMP

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×