【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 ...
随机推荐
- 面试题-javascript-面向对象编程
笔者在某次笔试中遇到这个题:印象很深. function ClassA() { var value=4; this.getValue= function() { return value; } thi ...
- TCP/IP和Socket开发经验分享
当前与网络相关的业务主要是基于tcp/ip或http,熟悉j2ee的同学一定会对http场景下的开发比较了解.但是,精通tcp/ip以及如何构建一个直接基于tcp/ip层通讯的知识却不太多见.恰巧,最 ...
- python语法入门之流程控制
python语法入门之流程控制 流程控制是指控制流程,具体指控制程序执行的流程. 流程控制分为三种: 1.顺序结构 程序从上而下的正常执行(正常执行的代码就是顺序结构) 2.分支结构 赋予程序人的思维 ...
- Windows 程序包管理器 Chocolatey:一条命令装软件
Windows 程序包管理器 Chocolatey:一条命令装软件 本文原始地址:https://sitoi.cn/posts/46278.html 介绍 Chocolatey 是一种软件管理解决方案 ...
- Linux 如何创建或删除以横杠(-)开头的文件或目录
小测试: [root@test test]# ls [root@test test]# touch -abc touch: invalid option -- 'b' Try `touch --hel ...
- 学习笔记62_python文件操作
#使用 str = raw_input("输入密码:") 来获取键盘的输入 #创建或打开一个文件 fp = open("hellow.txt","w& ...
- 如何做seo优化才能获取搜索引擎排名?
现在网络上有很多网站,但是排名和流量都不理想,所以很多企业会很苦恼.所以我们经常思考如何使网站被搜索引擎喜欢,被用户喜欢,有一个良好的排名和流量? 在这个鱼龙混杂的网络中,seo优化实际上是seo网站 ...
- 刷题翻车:python 布尔运算操作符的优先级
前两天在 xue.cn 体验答题挑战,我有道题做错了,却不明白错在哪里.题目大概如下,代码运行后将打印什么? if True or False and False: print('1') else: ...
- [考试反思]0904NOIP模拟测试37:守望
100分并列的还有4个没粘 总分是大脸的一半,然而还只低了2名.差距好大...但其实后面的分数段又很密集,和我都差不了多少... 我可能也是最水的那一个,排行榜前7个里面就我没有AC.全是暴力... ...
- docker compose网络设置
(系统:Centos 7.4 ,docker 版本:18.03.1-ce, docker-compose version 1.18.0) cat docker-compose.yml version: ...