解题:POI 2006 Periods of Words

题面

洛谷翻译有毒系列

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

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

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int N=1e6+6;
 6 int nxt[N],pro[N];
 7 long long n,p,ans;
 8 char ss[N];
 9 int main ()
10 {
11     scanf("%lld%s",&n,ss);
12     for(int i=1;i<n;i++)
13     {
14         while(p&&ss[i]!=ss[p]) p=nxt[p];
15         nxt[i+1]=(ss[i]==ss[p])?++p:0;
16     }
17     for(int i=1;i<=n;i++)
18         pro[i]=nxt[i]?pro[nxt[i]]:i,ans+=i-pro[i];
19     printf("%lld",ans);
20     return 0;
21 }
View Code
原文地址:https://www.cnblogs.com/ydnhaha/p/9741527.html