【Luogu P3375】字符串匹配KMP算法模板
- 模式串:即题目中的S2所代表的意义
- 文本串:即题目中的S1所代表的意义
对于字符串匹配,有一种很显然的朴素算法:在S1中枚举起点一位一位匹配,失配之后起点往后移动一位,从头开始进行匹配。
这种算法的时间复杂度几乎达到了\(O(nm)\),显然是不能接受的。
这种做法的缺点在于做了很多无用的匹配,并且每一次都从头开始匹配,完全忽略上一次匹配的信息。
而KMP算法就利用了上一次匹配的信息,减少匹配次数,时间复杂度仅有\(O(n)\)

(图片来自算法导论)
观察这样一张图。在第六位失配之后,按照朴素算法,我们把模式串后移一位,从头开始匹配。事实上后移一位的匹配根本不可能成功,根据上一次匹配得到的信息,因为文本串(灰色部分)中的第二位能够与模式串的第二位匹配,所以不可能与第一位匹配。而文本串(灰色部分)第三四五位恰好与模式串的第一二三位匹配,所以我们可以直接把模式串后移两位,重新开始匹配。

(图片来自算法导论)
如上图所示,这样可以减少很多不必要的匹配。
那么我们怎么才能知道让模式串偏移多少才合适呢?
下文的j是在模式串中的指针,j及其以前的字符是已经匹配的。
假设字符串在第j位失配,我们要找到一个尽可能长的长度\(L\),使\(S2[1..L]\)与\(S2[j-L,j]\)完全匹配(L<j),这样我们就可以在可以直接令\(j=L\),跳过前面L个的字符,因为他们绝对是匹配的。
结合代码及注释进行透彻的理解:(从KMP函数开始看更便于理解)
#include<cstdio>
#include<iostream>
using namespace std;
string s1,s2;
int nxt[1000005];
void Pre_do()
{
int len=s2.size();
nxt[0]=-1;//-1意味着从头开始匹配
for (int i=1,j=-1;i<len;i++)//注意i从1开始
{
while (j>=0&&s2[j+1]!=s2[i]) j=nxt[j];//假设不能匹配就跳过去。
//j一定小于i,所以此时的nxt[j]一定已经被记录了
if (s2[j+1]==s2[i]) j++;//匹配了就增加匹配长度
nxt[i]=j;//记录
}
}
int KMP()
{
int ret=0,len1=s1.size(),len2=s2.size();
for (int i=0,j=-1;i<len1;i++)
{
while (j>=0&&s2[j+1]!=s1[i]) j=nxt[j];//假设不能匹配就跳过去。
if (s2[j+1]==s1[i]) j++;//匹配了就增加匹配长度
if (j==len2-1) //匹配成功
{
ret++;
j=nxt[j];
printf("%d\n",i-len2+2);
}
}
return ret;
}
int main()
{
cin>>s1>>s2;
Pre_do();//预处理,求出每个位置失配后应该跳到哪个位置
KMP();
int len2=s2.size();
for (int i=0;i<len2;i++) printf("%d ",nxt[i]+1);
return 0;
}
【Luogu P3375】字符串匹配KMP算法模板的更多相关文章
- 字符串匹配KMP算法详解
1. 引言 以前看过很多次KMP算法,一直觉得很有用,但都没有搞明白,一方面是网上很少有比较详细的通俗易懂的讲解,另一方面也怪自己没有沉下心来研究.最近在leetcode上又遇见字符串匹配的题目,以此 ...
- 字符串匹配KMP算法
1. 字符串匹配的KMP算法 2. KMP算法详解 3. 从头到尾彻底理解KMP
- 字符串匹配--kmp算法原理整理
kmp算法原理:求出P0···Pi的最大相同前后缀长度k: 字符串匹配是计算机的基本任务之一.举例,字符串"BBC ABCDAB ABCDABCDABDE",里面是否包含另一个字符 ...
- 字符串匹配KMP算法的C语言实现
字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串"ABCDABD" ...
- 字符串匹配KMP算法的讲解C++
转自http://blog.csdn.net/starstar1992/article/details/54913261 也可以参考http://blog.csdn.net/liu940204/art ...
- 字符串匹配KMP算法(转自阮一峰)
转自 http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html 字符串匹配是计算 ...
- 字符串匹配——KMP算法
关于KMP算法的分析,我觉得这两篇博客写的不错: http://www.ruanyifeng.com/blog/2013/05/Knuth–Morris–Pratt_algorithm.html ht ...
- 字符串匹配—KMP算法
KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特-莫里斯-普拉特操作(简称KMP算法).KMP算法的核心是利用匹配失败后 ...
- P3375 【模板】KMP字符串匹配——kmp算法
先上一波题目 https://www.luogu.org/problem/P3375 kmp模板 看了好久才想起来是个什么东西qwq #include<cstdio> #include&l ...
随机推荐
- 宋宝华:Docker 最初的2小时(Docker从入门到入门)
本文系转载,著作权归作者所有. 商业转载请联系作者获得授权,非商业转载请注明出处. 作者: 宋宝华 来源: 微信公众号linux阅码场(id: linuxdev) 最初的2小时,你会爱上Docker, ...
- UNIX环境高级编程 使用方法
1.解压文件到apue.2e目录2.修改相应平台的文件,我使用的是linux,所以修改Make.defines.linux你修改的只需要这一行WKDIR=/home/your_dir/apue2e_s ...
- 第七篇 Flask实例化配置及Flask对象配置
一.Flask对象的配置 Flask 是一个非常灵活且短小精干的web框架 , 那么灵活性从什么地方体现呢? 有一个神奇的东西叫 Flask配置 , 这个东西怎么用呢? 它能给我们带来怎么样的方便呢? ...
- vue运行报错error:Cannot assign to read only property 'exports' of object '#<Object>'
用weex做项目的时候,npm start 之后一直报错error:Cannot assign to read only property 'exports' of object '#<Obje ...
- Mac OS 简易U盘重装系统 亲测
Mac OS 简易U盘重装系统 亲测 亲测可用!简单方便,本文描述尽可能详细,如有疑问欢迎留言or微信咨询:523331232 如有帮助欢迎点赞! (一)制作MacOS系统U盘 [步骤1 准备U盘] ...
- jvm虚拟机栈的作用
jvm虚拟机栈的作用 jvm虚拟机栈栈帧的组成 jvm虚拟机栈,也叫java栈,它由一个个的栈帧组成,而栈帖由以下几个部分组成 局部变量表-存储方法参数,内部使用的变量 操作数栈-在变量进行存储时,需 ...
- centos转ubuntu常见问题总结:
1.vmtools的安装 https://blog.csdn.net/weixin_41762173/article/details/79480832 2.镜像源替换 https://opsx.ali ...
- python基础-字典dict
字典-dict 用途: 定义方法:通过{} 来存储数据,通过key:value (键值对)来存储数据,每个键值对通过逗号分隔.在键值对中,key 是不可变的数据类型,value 是任意数据类型 def ...
- Unity1-HellowWord
1.新建一个Unity工程,选择3D类型项目. 2.目录下有: Assets是主要操作的目录. 3.面板 4.做一个简单的方块移动效果: 1.在Hierarchy面板中,点击Create-3D Obj ...
- [2018-01-12] python 当天学习笔记
Python模块 Python欧快(Moudule),是一个Python文件,以.py结尾,包含了Python对象定义和Python语句. 模块让你能够有逻辑地组织你的Python代码段. 把相关的代 ...