正题
评测记录:https://www.luogu.org/recordnew/lists?uid=52918&pid=P3435
大意
一个字符串,对于每个前缀,求复制一份放在末尾可以覆盖整个前缀的前缀,求所有的长度和。
解题思路
这道题如果暴力的话很简单,对于每个前缀每次往前跳,如果不可以覆盖了就下一个。
但是这样会被卡成
所有我们可以加一个优化,我们找一个最短的,然后总长度减去最短的就是最长的。我们就可以每次改变next的值,让他直接指向最短的,然后就可以
解决问题
code
#include<cstdio>
using namespace std;
int n,next[1000011];
char s[1000011];
long long ans;
int main()
{
scanf("%d",&n);
scanf("%s",s);
for(int i=1,j=0;i<n;i++)
{
while(j&&(s[i]!=s[j])) j=next[j];
j+=(s[i]==s[j]);next[i+1]=j;
}//匹配指针
int j;
for(int i=1;i<=n;i++)
{
j=i;
while(next[j]) j=next[j];//跳转
if(next[i]!=0)next[i]=j;//记忆化
ans+=i-j;//统计答案
}
printf("%lld",ans);
}