【题解】周期长度和

【题解】周期长度和

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

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

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

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

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

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

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

#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算法

posted @ 2022-06-03 22:00  Burnling  阅读(39)  评论(0编辑  收藏  举报