P3435 [POI2006] OKR-Periods of Words

网址:https://www.luogu.com.cn/problem/P3435

 

题目的要求是:

1.输入一个字符串a

2.找到一个a的前缀p——p的条件需满足  ① p为a的前缀

                  ② p≠a

3.用字符串Q表示a的周期 <==> Q为a的p前缀,同时a为 Q+Q 的前缀

4.所求为 a 的所有前缀的最大周期之和

 

也就是说 对于给定的字符串 a ,我们需要先确定其每一个前缀p[i]。

求出其中最长的,使得 p[i] + p[i] 能够被原来的字符串 a 覆盖。

最后求出所有的、这些能满足的长度和。

 对于每个前缀i,令j=i,然后在j>0的情况下令j=next[j],最小的j就是答案,此时ans+=i-j

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
 
using namespace std;
 
char a[1000010];
int n,fail[1000010];//先定义两个用于储存的组
 
int main(){
    scanf("%d",&n);//先输入字符串a的长度
 
    scanf("%s",a);//字符串a的输入
 
    int i,j;
 
    ll ans=0;//这个ll就是前面定义的#define ll long long
 
    fail[0]=fail[1]=0;//初始化fail的第一第二个元素为0
 
    j=0;
 
    for(i=1;i<n;i++){//第一个循环,从1到n,遍历
 
        while(j&&(a[i]!=a[j])) {//这里就是通过j以及以及a[i]与a[j]来判断
            j=fail[j];//将fail[j]的值赋予j
        }  
        j+=(a[i]==a[j]);//这里是当 a[i] 与 a[j] 的值相等时,j++
 
        fail[i+1]=j;//将j的值保存在后一个fail里
    }
 
    for(i=1;i<=n;i++){
        j=i;   
 
        while(fail[j]) {//用while循环来获取可能的j值
            j=fail[j];
        }//这个循环通过fail[j]的值来获取,当fail[j]≠0时继续,直到获取到使得fail[j]=0的前一个j值
 
        if(fail[i]!=0) {
            fail[i]=j;
        }//当fail[i]≠0时,令fail[i]=j
        ans+=i-j;//ans=ans+i-j
    }
    printf("%lld",ans);
 
}

 

参考代码地址:https://www.luogu.com.cn/blog/dedicatus545/solution-p3435

 

 

  

 

posted @   syxw  阅读(33)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示