解题:POI 2006 Periods of Words

时间:2025-03-07 18:03:08

题面

洛谷翻译有毒系列

正常人能看懂的题面:若$S$可以通过前缀$s$重复若干次(可重叠)来表示($s!=S$),则称$s$是$S$的一个循环串。求一个字符串所有前缀(包括本身)的最长循环串的长度之和。

根据$nxt$数组的定义,显然每个串的答案是$len-nxt'$,这里的$nxt'$表示最小的前缀=后缀,当$nxt=0$时没有贡献,然后我们可以每次向前跳$nxt$,记忆化之后就是$O(n)$的

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e6+;
int nxt[N],pro[N];
long long n,p,ans;
char ss[N];
int main ()
{
scanf("%lld%s",&n,ss);
for(int i=;i<n;i++)
{
while(p&&ss[i]!=ss[p]) p=nxt[p];
nxt[i+]=(ss[i]==ss[p])?++p:;
}
for(int i=;i<=n;i++)
pro[i]=nxt[i]?pro[nxt[i]]:i,ans+=i-pro[i];
printf("%lld",ans);
return ;
}