luogu 3426题解 (KMP)
题面
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);
}
luogu 3426题解 (KMP)的更多相关文章
- [BZOJ 1535] [Luogu 3426]SZA-Template (KMP+fail树+双向链表)
[BZOJ 1535] [Luogu 3426]SZA-Template (KMP+fail树+双向链表) 题面 Byteasar 想在墙上涂一段很长的字符,他为了做这件事从字符的前面一段中截取了一段 ...
- BZOJ 1100 &&luogu 3454(计算几何+KMP)
题面 给定一个多边形,求对称轴数量. 分析 初看这似乎是一道计算几何的题目,但是如果暴力枚举对称轴,再去判断对称轴两边的边和角是否相等,时间复杂度为\(O(n^2)\),显然会TLE 问题转换 顺时针 ...
- POJ3080 Blue Jeans 题解 KMP算法
题目链接:http://poj.org/problem?id=3080 题目大意:给你N个长度为60的字符串(N<=10),求他们的最长公共子串(长度>=3). 题目分析:KMP字符串匹配 ...
- HDU1711 Number Sequence 题解 KMP算法
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1711 题目大意:最基础的字符串匹配,只不过这里用整数数组代替了字符串. 给你两个数组 \(a[1..N ...
- HDU1686 Oulipo 题解 KMP算法
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1686 题目大意:给你一个子串t和一个母串s,求s中有多少个子串t. 题目分析:KMP模板题. cal_ ...
- HDU3336 Count the string 题解 KMP算法
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3336 题目大意:找出字符串s中和s的前缀相同的所有子串的个数. 题目分析:KMP模板题.这道题考虑 n ...
- Luogu P1993 题解
p1993 小康的农场 CSP_S 1=之后就没怎么写题解.. 推荐博客食用 预备知识 明显这是一道差分约束的题,以下简称差分 有些人可能不了解差分,请点 [传送门] 至于用差分做的题的特征,无一都是 ...
- HDU3746 Teacher YYF 题解 KMP算法
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3746 题目大意:给你一个串 \(s\) ,要求 \(s\) 的开头或结尾添加最少的字符,使得添加后的串 ...
- POJ2185 Milking Grid 题解 KMP算法
题目链接:http://poj.org/problem?id=2185 题目大意:求一个二维的字符串矩阵的最小覆盖子矩阵,即这个最小覆盖子矩阵在二维空间上不断翻倍后能覆盖原始矩阵. 题目分析:next ...
随机推荐
- 【前端】HTML基础
前端 HTML:一个人 CSS:这个人的衣服 JS:这个人的行为 1 head标签 head相关标签 <!--html5--> <!DOCTYPE html> <html ...
- 【UOJ#400】暴力写挂
题目链接 题意 两棵树 , 求出下面式子的最大值. \[dep[u]+dep[v]-dep[LCA(u,v)]-dep'[LCA'(u,v)]\] Sol 边分治. 与第一棵树有关的信息比较多,所以对 ...
- Arduino库
单总线库: 下载地址 : 链接:https://pan.baidu.com/s/1YSuqrXWuBAxMEUWHy8rckw 提取码:svix 把整个文件夹复制到 Arduino安装目录的 ...
- ES6 Module(模块)
1.export命令 一个模块就是一个独立的文件. 该文件内部的所有变量,外部无法获取. 如果你希望外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量. 下面是一个 JS 文件,里 ...
- Vue中 axios+QS 插件往后台传参
之前用Vue+element写了一个后台管理系统,在登录时使用axios请求数据传参时无法正常的获取数据.发现原因是传递参数要将参数序列化.这里使用了qs插件: 简单来说,qs 是一个增加了一些安全性 ...
- 048:ORM模型基本的增删改查操作
ORM对数据库的增删改查基本操作: 创建模型如下: 基本的增删改查如下:
- C# 实现二维数组的排序算法(代码)
class Order { /// <summary> /// 对二维数组排序 /// </summary> /// <param name="values&q ...
- 【bzoj2733】[HNOI2012]永无乡
题目描述: 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以从一个岛 到 ...
- 【翻译】详解HTML5 自定义 Data 属性
原标题:HTML5 Custom Data Attributes (data-*) 你是否曾经使用 class 或 rel 来保存任意的元数据,只为了使你的JavaScript更简单?如果你回答是的, ...
- win10 1903
Windows 10 v1903/19H1 and Windows Server 2019 v1903/19H1 will hang or BSOD during power-on when vIOM ...