
为什么可以用 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算法