0%

【题解】周期长度和

为什么可以用 KMP 解决这道题

根据 $\text{proper}$ 前缀及周期的定义可知,

如果 $A$ 存在周期,那么 $A$ 一定有公共前后缀,周期为 $A$ 的长度减去公共前后缀的长度

既然要求最大周期长度,那么就需要令公共前后缀最短

而 $\operatorname{KMP}$ 预处理出来的 $\pi$ 数组表示的就是前缀串的最长公共前后缀长度

通过 $\pi$ 数组不断向前跳,可以找到最短公共前后缀长度(代码实现就是上面跟并查集似的那四行)

这样就可求所有前缀的最大周期长度之和了

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
#include<bits/stdc++.h>
using namespace std;

const int maxN = (1e6+5);

char S[maxN];

int N;
int pi_[maxN];

inline void pre(){
int j = 0;
for(int i = 2;i<=N;i++){
while(j && S[j+1] != S[i]) j = pi_[j];
if(S[j+1] == S[i]) j++;
pi_[i] = j;
}
}

int find(int x){
if(pi_[x]) return pi_[x] = find(pi_[x]);
return x;
}

int main(){
scanf("%d\n",&N);
scanf("%s",S+1);
pre();
long long ans = 0;
for(int i = 1;i<=N;i++){
ans += 1ll * i - 1ll * find(i);
}
printf("%lld",ans);
return 0;
}

不算总结的总结

涉及到公共前后缀的问题可以考虑KMP算法