码迷,mamicode.com
首页 > 其他好文 > 详细

OKR-Periods of Words

时间:2019-11-03 18:04:56      阅读:57      评论:0      收藏:0      [点我收藏+]

标签:amp   http   一个   n+1   word   char s   while   优化   std   

https://loj.ac/problem/10046

题目描述

??定义字符串\(Q\)为字符串\(A\)的周期,当且仅当\(Q\)\(A\)的前缀(不等于A),且\(A\)\(QQ\)的前缀。求所有前缀的最大周期长度之和。

思路

??我们看数据范围,显然要\(O(n)\)处理,所以我们对每一个前缀都应该用常数级的复杂度找到其最大周期。我们考虑周期的定义,实际上就是要找到一段\(Q=A[ 1...len]\),并且\(A[len+1...n] = Q [1...n-len ]\),因此\(A[1...n-len]=A[len+1...n]\),这就是\(KMP\)所求的,最长公共前后缀。所以最大周期就是\(n-\)最短公共前后缀,因为\(Q=n-\)公共前后缀。所以我们不断\(j=p[j]\),这样得到最小值就是我们求得最短公共前后缀,答案加上即可。不过由于一步步跳效率会低,我们可以优化,一次跳完直接更新\(p\)数组。

代码

#include <bits/stdc++.h>
using namespace std;
const int MAXN=1e6+10;
char s[MAXN];
int pre[MAXN];
int main() 
{
    int n;
    scanf("%d",&n);
    scanf(" %s",s+1);
    int j=0;pre[1]=0;
    for(int i=1;i<n;i++)
    {
        while(j>0&&s[i+1]!=s[j+1])j=pre[j];
        if(s[i+1]==s[j+1])j++;
        pre[i+1]=j;
    }
    long long ans=0;
    for(int i=1;i<=n;i++)
    {
        j=i;
        while(pre[j])j=pre[j];
        if(pre[i]!=0)pre[i]=j;        //优化 
        ans+=i-j;
    }
    printf("%lld",ans);
    return 0;
}

OKR-Periods of Words

标签:amp   http   一个   n+1   word   char s   while   优化   std   

原文地址:https://www.cnblogs.com/fangbozhen/p/11788186.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!