《ybtoj高效进阶》第二部分第三章例题3 周期长度和

题目大意

串是有限个小写字母的序列,特别的,一个空序列也可以是一个串。一个串 P P P是串 A A A的前缀,当且仅当存在串 B B B满足 A = P B A=PB A=PB。如果 P ≠ A P≠A P=A并且 P P P不是一个空串,那么我们说 P P P A A A的一个 proper 前缀。

定义 Q Q Q A A A的周期,当且仅当 Q Q Q A A A的一个 proper 前缀并且 A A A Q Q QQ QQ的前缀(不一定要是 proper 前缀)

给出一个串,求出它所有前缀的最大周期长度之和。

思路

显然,一个串的proper前缀长度肯定为该串长度-最小循环节长度,而最小循环节可以这样求:

long long find(long long x)
{
    
    
	if (p[x]!=0) return find(p[x]);
	return x;
}

慢着,这玩意怎么这么像并查集?
没错,它的性质与并查集类似,也可以路径压缩!
所以代码在这里:(不开long long见祖宗)
code:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
using namespace std;
long long p[1000006],n,m,ans;
string b;
inline void f()
{
    
    
	p[1]=0;
	long long i=1,j=0;
	while (i<m)
	{
    
    
		while (j&&b[1+j]!=b[1+i]) j=p[j];
		if (b[1+j]==b[1+i]) j++;
		p[i+1]=j;
		i++;
	}
	return;
}
long long find(long long x)
{
    
    
	if (p[x]!=0) return p[x]=find(p[x]);
	return x;
}
int main()
{
    
    
	cin>>m;
	cin>>b;
	b.insert(0," ");
	f();
	for (long long i=1;i<=m;i++)
	{
    
    
		ans+=i-find(i);
	}
	cout<<ans;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_49843717/article/details/115213593
今日推荐