洛谷翻译有毒系列
正常人能看懂的题面:若$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 }