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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现