字符串匹配算法之kmp算法
kmp算法是一种效率非常高的字符串匹配算法,是由Knuth,Morris,Pratt共同提出的模式匹配算法,所以简称KMP算法
算法思想
在一个字符串中查找另一个字符串时,会遇到如下图的情况

我们通常的做法是从第一个串A的下一位B再逐位比较,但这样的做法非常低效。
仔细思考一下发现,第一个串已经匹配的部分就是第二个串的前缀。如果我们对第二个串进行一些预处理,或许就不用再去逐位比较了。
KMP算法就是预处理出要查找串每个前缀的最大相同前后缀的长度,通俗一点就是两个相同的串在不重合情况下最大的重叠长度
如上图中ABCDAB前缀的最大相同前后缀就是AB,长度为2

这样我们在D匹配不成功时,就可以直接将查找串后移到第一个仍然能匹配成功位置(要找的串的比较位置前移到最大相同前后缀中前缀的下一个位置),如下图:最大相同前后缀为AB,移到下一个位置C

如果还匹配不成功,则继续将查找串后移到第一个仍然能匹配成功位置,发现没有,就从头比较

这时从头比较也不成功,就将两个的比较位置都后移
总结:
- 如果两个串比较位置相等,则向后比较
- 如果不相等,则将要找的串后移到第一个仍然能匹配成功的位置(要找的串的比较位置前移到最大相同前后缀中前缀的下一个位置)
求最大相同前后缀(用next数组存储)

对于上图的字符串,它的前三个前缀没有最大相同前后缀
第四个前缀ABDA,因为第一个字符和最后一个字符相同,所以它的最大相同前后缀为1
第五个前缀,只需比较第四个前缀最大相同前后缀的后一个字符和最后一个字符(第一个B和第二个B)就行了,
如果相等,则第五个前缀最大相同前后缀长度=第四个前缀最大相同前后缀长度+1,并且一定是最大的
重点:如果最后一个字符与前一个前缀的最大相同前后缀的后一个字符不相等
考虑
的最大相同前后缀
前一个前缀
的最大相同前后缀是
但最后一个字符D不等于最大相同前后缀的下一个字符C
这时字符串的最大相同前后缀一定小于5了,并且ABDAB已经匹配成功
我们就要再找后缀ABDAB的一个后缀与前缀ABDAB的一个前缀进行匹配,
这就是前缀ABDAB的最大相同前后缀AB。
我们比较
的最后一个字符D和前缀
的下一个字符D发现它们相等,则
的最大相同前后缀为ABD。
总结一下
- 如果当前前缀的最后一个字符与上一个最大相同前后缀(上一个前缀的最大相同前后缀,以下简称)的下一个字符相等,则当前前缀的最大相同前后缀长度=上一个最大相同前后缀长度+1
- 如果当前前缀的最后一个字符与上一个最大相同前后缀的下一个字符不相等,则将上一个最大相同前后缀变为它的最大相同前后缀,继续比较,直到相等,或上一个最大相同前后缀变为0
代码:
inline void Next(const char a[],int next[],int l){//a为字符串,l为字符串长度 ,next为前缀的最大相同前后缀长度
for(int i=,k=;i<l;i++){//i表示当前计算到第i个前缀,k表示上一个最大相同前后缀长度
while(k>&&a[i]!=a[k]){//上一个最大相同前后缀长度>0并且不相等
k=next[k-];
}
if(a[i]==a[k])k++;//相等就为上一个最大相同前后缀长度+1,不相等就是0;
next[i]=k;
}
}
KMP算法代码
inline void kmp(const char a[],const char b[],int next[],int l1,int l2){//a为文章,b为要查找的串,l1是a的长度,l2是b的长度
for(int i=,q=;i<l1;i++){
while(q>&&b[q]!=a[i])q=next[q-];//如果不相等,则b后移到第一个仍然能匹配成功位置(相当于b串的比较位置前移到next[q-1]+1,这里因为是从0开始所以比较位置前移到next[q-1])
if(b[q]==a[i])q++;//相等就向后比较
if(q==l2){//成功匹配
v[i]=;//i为成功匹配的a末尾的位置,可以进行其他操作
}
}
}
图片来源:https://www.cnblogs.com/zhangtianq/p/5839909.html
字符串匹配算法之kmp算法的更多相关文章
- 字符串匹配算法之 kmp算法 (python版)
字符串匹配算法之 kmp算法 (python版) 1.什么是KMP算法 KMP是三位大牛:D.E.Knuth.J.H.MorriT和V.R.Pratt同时发现的.其中第一位就是<计算机程序设计艺 ...
- 动画演示Sunday字符串匹配算法——比KMP算法快七倍!极易理解!
前言 上一篇我用动画的方式向大家详细说明了KMP算法(没看过的同学可以回去看看). 这次我依旧采用动画的方式向大家介绍另一个你用一次就会爱上的字符串匹配算法:Sunday算法,希望能收获你的点赞关注收 ...
- 字符串匹配算法之————KMP算法
上一篇中讲到暴力法字符串匹配算法,但是暴力法明显存在这样一个问题:一次只移动一个字符.但实际上,针对不同的匹配情况,每次移动的间隔可以更大,没有必要每次只是移动一位: 关于KMP算法的描述,推荐一篇博 ...
- 字符串匹配算法(三)-KMP算法
今天我们来聊一下字符串匹配算法里最著名的算法-KMP算法,KMP算法的全称是 Knuth Morris Pratt 算法,是根据三位作者(D.E.Knuth,J.H.Morris 和 V.R.Prat ...
- Python 细聊从暴力(BF)字符串匹配算法到 KMP 算法之间的精妙变化
1. 字符串匹配算法 所谓字符串匹配算法,简单地说就是在一个目标字符串中查找是否存在另一个模式字符串.如在字符串 "ABCDEFG" 中查找是否存在 "EF" ...
- 数据结构学习之字符串匹配算法(BF||KMP)
数据结构学习之字符串匹配算法(BF||KMP) 0x1 实验目的 通过实验深入了解字符串常用的匹配算法(BF暴力匹配.KMP.优化KMP算法)思想. 0x2 实验要求 编写出BF暴力匹配.KM ...
- 字符串匹配算法之Sunday算法(转)
字符串匹配算法之Sunday算法 背景 我们第一次接触字符串匹配,想到的肯定是直接用2个循环来遍历,这样代码虽然简单,但时间复杂度却是Ω(m*n),也就是达到了字符串匹配效率的下限.于是后来人经过研究 ...
- 字符串匹配算法之BM算法
BM算法,全称是Boyer-Moore算法,1977年,德克萨斯大学的Robert S. Boyer教授和J Strother Moore教授发明了一种新的字符串匹配算法. BM算法定义了两个规则: ...
- 数据结构4_java---顺序串,字符串匹配算法(BF算法,KMP算法)
1.顺序串 实现的操作有: 构造串 判断空串 返回串的长度 返回位序号为i的字符 将串的长度扩充为newCapacity 返回从begin到end-1的子串 在第i个字符之前插入字串str 删除子串 ...
随机推荐
- c#使用打印机
在windows应用程序中文档的打印是一项非常重要的功能,在以前一直是一个非常复杂的工作,Microsoft .net Framework的打印功能都以组件的方式提供,为程序员提供了很大的方便,但是这 ...
- [笔记]180612 for DevOps
adb devices 识别不了安卓手机:我下的adb interface驱动下载链接:如果设备管理器中ADB Interface是黄色的,就需要先安装adb interface驱动(BD:adb i ...
- css实现字母或数字强制换行
//换行white-space:normal;word-break:break-all;word-wrap: break-word; 相关属性white-space: normal|pre|nowra ...
- MySQL操作表和表记录
目录 操作表 增 列约束 列类型 删 改 修改表名 增加字段 修改字段 删除字段 查 复制表结构 操作表数据 增 删 改 查 操作表 增 创建表语法 创建一个表,多个字段: create table ...
- C语言利用动态数组实现顺序表(不限数据类型)
实现任意数据类型的顺序表的初始化,插入,删除(按值删除:按位置删除),销毁功能.. 顺序表结构体 实现顺序表结构体的三个要素:(1)数组首地址:(2)数组的大小:(3)当前数组元素的个数. //顺序表 ...
- centos7 搭建 php7 + nginx (2)
安装php php下载地址 # 避免出错,先安装下面 yum install libzip libzip-devel libxml2-devel openssl openssl-devel bzip2 ...
- nc 文件的nan识别
表现形式:print()结果为 -- 打印type为numpy.ma.core.MaskedConstant 使用 if type(x) == np.ma.core.MaskedConsta ...
- 密码学笔记(4)——RSA的其他攻击
上一篇详细分析了几种分解因子的算法,这是攻击RSA密码最为明显的算法,这一篇中我们考虑是否有不用分解模数n就可以解密RSA的密文的方法,这是因为前面也提到,当n比较大的时候进行分解成素数的乘积是非常困 ...
- 最大似然估计(Maximum likelihood estimation)
最大似然估计提供了一种给定观察数据来评估模型参数的方法,即:"模型已定,参数未知".简单而言,假设我们要统计全国人口的身高,首先假设这个身高服从服从正态分布,但是该分布的均值与方差 ...
- leetcode 1078 Occurrences After Bigram
lc1078 Occurrences After Bigram trim().split()将原字符串转换成words数组 依次匹配first和second,若两者都能匹配上,则下一个单词为third ...