题面

Byteasar 想在墙上涂一段很长的字符,他为了做这件事从字符的前面一段中截取了一段作为模版. 然后将模版重复喷涂到相应的位置后就得到了他想要的字符序列.一个字符可以被喷涂很多次,但是一个位置不能喷涂不同的字符.做一个模版很费工夫,所以他想要模版的长度尽量小,求最小长度是多少.拿样例来说 ababbababbabababbabababbababbaba , 模版为前8个字符ababbaba, 喷涂的过程为: ababbababbabababbabababbababbaba

分析

仔细分析题意之后我们可以发现模板串的三条性质:

1.一个模板串A是要求的文本串B的公共前后缀

2.如果一个模板串B可以覆盖模板串A,那么B是比A更优的一个解

3.如果模板串A可以完全覆盖文本串B,那么A在B中的匹配位置(按照开头算)之间的空格数小于A的长度

由性质1可以猜想,此题大概率是用KMP求解,因为KMP正好可以求出公共前后缀长度。

因此,设next[i]表示前i位的公共前后缀长度,则序列长度只能为next[n],next[next[n]]...

将可能的长度存进数组,对于每个长度的前缀,将其和原串进行匹配,再利用性质3进行判断。

但是这样仍然会超时。

优化:从小到大枚举长度,只要有一个合法就退出。对于长度a,记录最远的匹配位置mx,若存在另

一个长度为b的模板串,且b<mx,则a可以完全覆盖b, 故b一定没有a优。由于a不可行(a在b之前被枚举,若a可行,就不会枚举b了),b一定也不可行,直接跳过

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 500005
using namespace std;
int n,m,sz;
int next[maxn];
int f[maxn];
int len[maxn];
char a[maxn],b[maxn];
int mx;
int check(int m){for(int i=1,j=0;i<=n;i++){while(j>0&&(j==m||b[i]!=a[j+1]) )j=next[j];if(b[i]==a[j+1]) j++;f[i]=j;}bool flag=false;int last=1;for(int i=1;i<=n;i++){if(f[i]==m){flag=true;if(i-last-1>=m) return 0;last=i;mx=max(mx,i);}}if(flag) return 1;else return 0;
}
int main(){scanf("%s",a+1);n=strlen(a+1);next[1]=0;for(int i=1;i<=n;i++) b[i]=a[i];for(int i=2,j=0;i<=n;i++){while(j>0&&a[i]!=a[j+1]) j=next[j];if(a[i]==a[j+1]) j++;next[i]=j;}sz=0;for(int i=n;i;i=next[i]){len[++sz]=i;}int ans=n;for(int i=sz;i>=0;i--){if(len[i]<=mx) continue;if(check(len[i])){ans=len[i];break;}}printf("%d\n",ans);
} 

转载于:https://www.cnblogs.com/birchtree/p/9862061.html

luogu 3426题解 (KMP)相关推荐

  1. Luogu P2524题解

    题目描述: 这个题目和P2525很相似,但是问法不同,这个题问的是给你一个既定序列,问这个序列是所有排列中的第几小的. 题解: 这个题目有两种思路,其中一个是STL的prev_permutation( ...

  2. Luogu P1497题解

    题目描述: 有一个n * n的方形区域,同时你有k个木牛流马,同时这k个木牛流马有h种颜色,现在规定两个木牛流马不能同时存在于一行或者一列里面,现在问有几种放置方法? 题解 组合数学问题,这个题目整体 ...

  3. Luogu P2708 硬币翻转 题解

    Luogu p2708题解 思路: 由于我们这个题目的长度不知道,所以我们不能一次性输入所有的硬币的状态,也许会爆数组(Ps:我没试过我不是知道).所以我们为了保险采取用getchar()一个一个读入 ...

  4. 题解 [LuoguP3426][POI2005]SZA-Template

    Luogu Link 题解 P3426(kmp) 首先求出 next\text{next}next 数组(记为 nxtinxt_inxti​). 设 fif_ifi​ 表示印制 [1,i][1,i][ ...

  5. luogu P3786 萃香抱西瓜

    P3786 萃香抱西瓜 题目背景 伊吹萃香(Ibuki Suika)正在魔法之森漫步,突然,许多西瓜(Suika)从四周飞来,划出了绚丽的轨迹.虽然阵势有点恐怖,但她还是决定抱走一些西瓜. 题目描述 ...

  6. 学习KMP (概念 + 模板 + 例题: 子串查找)

    我又回来了,感jio这几天有点勤啊!! 这一次我带着KMP来了, 文章目录 KMP介绍 模板 例题: 子串查找 题目 暴力题解 KMP题解 代码实现 KMP介绍 KMP,即 Knuth-Morris- ...

  7. 【线段树】[LUOGU 守墓人] [LUOGU 维护序列] 线段树模板题

    题目: 题目链接:[LUOGU 守墓人] 题解: 线段树单点修改,区间修改,单点查询,区间查询,一系列线段树基本操作,模板打就好. (回头再补一个分块和树状数组的这种板子题,就是用分块和树状数组再写一 ...

  8. Acwing算法基础课学习笔记(四)--数据结构之单链表双链表模拟栈模拟队列单调栈单调队列KMP

    单链表 算法题中最常考的单链表就是邻接表(用来存储图和数),比如最短路问题,最小生成树问题,最大流问题.双链表用于优化某些问题. 利用数组来表达单链表:存储值和指针的两个数组利用下标进行关联. 需要注 ...

  9. 题解 | The Biggest Water Problem

    字节 字节2024年校园招聘内推开始啦,快来投递你心仪的职位吧校招投递链接: https://jobs.bytedance.com/campus/position?r 百度2024测开二面 自我介绍项 ...

最新文章

  1. 没有安装提供程序“System.Data.SqlServerCe.3.5”的解决方法
  2. [置顶] C# 邮件发送方法【NetMail方式】
  3. POJ 1279 Art Gallery 半平面交 多边形的核
  4. 基于http的netty demo
  5. OSI参考模型(应用层、表示层、会话层、传输层、网络层、数据链路层、物理层)...
  6. Python爬虫之(四)urllib库的高级用法
  7. 阶段3 3.SpringMVC·_04.SpringMVC返回值类型及响应数据类型_7 响应json数据之发送ajax的请求...
  8. python3调用js_关于python3运行JS文件的问题
  9. 微信小程序 this.data与this.setData
  10. Zotero入门——安装插件
  11. 音频3A测试 AGC自动增益测试
  12. 基恩士KEYENCE激光打标机控制器维修ML-9110详解
  13. 联想服务器改xp系统,联想win7改xp蓝屏怎么解决
  14. 怦然心动(Flipped)-5
  15. 【高数】交换二次积分次序时,为什么要观察上下限大小关系?
  16. 计算机管理信息阶段性测验答案,管理信息系统阶段性学习测验一试题及答案(14页)-原创力文档...
  17. 风云编程python基础语法(5)
  18. MATLAB Support Package for USB Webcams 的使用方法(MATLAB调用摄像头后的使用方法)
  19. matlab中za是什么意思,MATLAB基础
  20. vc不支援此种界接口_护肤圈人人在夸的“早C晚A”,做完功课后我发现:不一定适合你!...

热门文章

  1. csapp炸弹实验_bomb_lab详解
  2. 分享调试SI4432的一些小经验
  3. 第十六章 - 垃圾回收相关概念
  4. LCD1602液晶显示屏学习笔记
  5. gmail头像,字母头像(如Gmail Android最佳做法)
  6. 用bmfont工具生成.fnt文件,但合成图片会分开问题
  7. 贵阳骑龙村:一根小香葱闯出大市场
  8. 写接口给京东使用的过程中学到的学习方法
  9. CentOS 8.5.111与历史版本的下载、CentOS YUM配置
  10. 剪映怎么去水印,剪映怎么剪辑视频