正题
评测记录:https://www.luogu.org/recordnew/lists?uid=52918&pid=P3435
大意
一个字符串,对于每个前缀,求复制一份放在末尾可以覆盖整个前缀的前缀,求所有的长度和。
解题思路
这道题如果暴力的话很简单,对于每个前缀每次往前跳,如果不可以覆盖了就下一个。
但是这样会被卡成O(n2)O(n2)
所有我们可以加一个优化,我们找一个最短的,然后总长度减去最短的就是最长的。我们就可以每次改变next的值,让他直接指向最短的,然后就可以O(n)O(n)解决问题
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);
}