P3435-[POI2006]OKR-Periods of Words【KMP】

正题

评测记录:https://www.luogu.org/recordnew/lists?uid=52918&pid=P3435


大意

一个字符串,对于每个前缀,求复制一份放在末尾可以覆盖整个前缀的前缀,求所有的长度和。


解题思路

这道题如果暴力的话很简单,对于每个前缀每次往前跳,如果不可以覆盖了就下一个。
但是这样会被卡成 O ( n 2 )
所有我们可以加一个优化,我们找一个最短的,然后总长度减去最短的就是最长的。我们就可以每次改变next的值,让他直接指向最短的,然后就可以 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);
}

猜你喜欢

转载自blog.csdn.net/Mr_wuyongcong/article/details/81780336