题目大意
串是有限个小写字母的序列,特别的,一个空序列也可以是一个串。一个串 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;
}