algorithm@ KMP
一. KMP算法
KMP算法是一种改进的字符串匹配算法,由D.E.Knuth与V.R.Pratt和J.H.Morris同时发现,简称KMP算法。KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息。
二. KMP算法的意义
先举一个简单模式匹配的例子,给定字符串T=“abababca”,S=“bacbababaabcbab”,判断T是否是S的子串,如果用暴力扫描的话,就是拿着T字符串从S的头扫到尾。这样的时间复杂度最坏情况下是O(n*m),其中n和m分别是主串和模式串的长度。而KMP算法的时间消耗是O(n+m)的,至于为什么这样,下面再说。
三. KMP算法的核心
KMP的核心就是一张表,我们称之为部分匹配表,起初我看这张表的时候也是云山雾绕,不知所云,部分匹配表是为模式串T专门设计的,T中每个字符对应着一个整数值,(这个地方也是困扰了我很久),现在我尽可能说得明白一些。首先下面附上一张T为“abababca”的部分匹配图,让大家“先睹为快”,看看部分匹配表是个什么东东。

好了,现在我们有了一个含有8个字符的模式串T,那么最后一行的value值是怎么得来的呢?别急,我先介绍相关概念:前缀和后缀,就拿字符串”abca“来说,”abca“的前缀有{a,ab,abc},”abca”的后缀有“bca,ca,a”,怎么样,很好理解对吧?一个字符串的前缀就是除了该字符串的最后一个字符以外的从首字符开始的连续字符串(自己胡乱下的定义,可能不准确,不过没关系,理解意思就行),后缀定义也类似。那么像字符串”a“就既没有前缀也没有后缀。
有了上面这两个概念,我们就可以得出value是怎么来的了。value值就是"前缀"和"后缀"的最长的共有元素的长度,这里就直接讲解例子帮助消化理解。首先我们把目光聚焦到index=0位的字符‘a’上来,字符串”a“没有前缀,没有后缀,共有元素为0,所以value[0]=0。然后index=1,字符串”ab“,前缀集合为{a},后缀集合为{b},没有共有元素,value[1]=0。index=2,字符串“aba”,前缀集合为{a,ab},后缀集合为{ba,a},共有元素为{a},取长度最长的,所以value[2]=1. index=3,字符串“abab”,前缀集合为{a,ab,aba},后缀集合为{bab,ab,b},共有元素为{ab},value[3]=2. index=4,字符串“ababa”,前缀集合为{a,ab,aba,abab},后缀集合为{baba,aba,ba,a},共有元素为{aba},所以value[4]=3. index=5,字符串“ababab”,前缀集合为{a,ab,aba,abab,ababa},后缀集合为{babab,abab,bab,ab,b},共有元素是{abab,ab},value[5]=4. index=6,字符串“abababc”,前缀集合是{a,ab,aba,abab,ababa,ababab},后缀集合是{bababc,ababc,babc,abc,bc,c},没有共有元素,所以value[6]=0. index=7,字符串“abababca”,前缀集合是{a,ab,aba,abab,ababa,ababab,abababc},后缀集合是{bababca,ababca,babca,abca,bca,ca,a},共有元素是{a},value[7]=1.这下算出value来应该是驾轻就熟了吧。
四. KMP算法运行
部分匹配表我们已经可以算出来了,现在就是要用这张表来运行KMP算法。这里以T=“abcdabd”,S=“abcdab abcdabcdabde”为例说明,这里首先给出T的部分匹配表:


初始状态,‘d’和‘ ’不匹配,但是‘d’前面的部分“abcdab”匹配,所以我们查询部分匹配表,得到value[5]=2,所以我们把T向右移动(6-2)个单位,6是部分匹配的长度,2是部分匹配字符串的value值。

如红线标注,’c‘和’ ‘不匹配,但是’c‘前面部分“ab”部分匹配,所以我们查表,得到value[1]=0,所以我们吧T向右移动(2-0)个单位。2是部分匹配的长度,0表示value值。

如红线标注,’a‘和’ ‘不匹配,而且’a‘前面什么也没有,就也没有部分匹配,那部分匹配表中查不到怎么办呢?对于这种情况,我们默认是T向右移动一个单位。

如红线所示,’c‘与’d‘不匹配,但是T中’d'以前的部分”abcdab“匹配了,所以我们查询部分匹配表,value[5]=2,所以模式串T向右移动(6-2)个单位。

“SUCCESS!”,我们找到了S的子串与T相等。如果你只想找到S中的一处与T相等,那么你就可以终止算法了,如果你还想找到S中第二个出现“ancdabd”的位置,那么你就向右移动(7-0)位,后面的过程和上面一样的,这里就不再赘述。
五. 总结
可能大家会发现部分匹配表与我们在书本上或者一些博客上看到的不一样,书本上用的是next数组,next[x]中的x表示的是匹配失败处字符的下标,假设我们在匹配的过程中发现T[x]!=S[i] (1<=i<=s.len),那么我们就查看T[1],T[2],...T[x-1]的部分匹配值,对!,就是上面讲的部分匹配表!回顾上面的例子我们可以发现,当T[x]处匹配失败时,我们查看的value[x-1]处的值,换言之,next[x]=value[x-1]!!。所以我们会看到next[0]=-1,因为没有value[-1]这种东西嘛~~。
六. next数组的源代码
void getNext(char *T){
int j=,k=-;
next[]=-;
while(j<strlen(T)-1){
if(k==-||T[j]==T[k]){
j++; k++;
next[j]=k;
}
else k=next[k];
}
}
algorithm@ KMP的更多相关文章
- Algorithm --> KMP算法
KMP算法 一.传统字符串匹配算法 /* * 从s中第sIndex位置开始匹配p * 若匹配成功,返回s中模式串p的起始index * 若匹配失败,返回-1 */ ) { ; || p.length( ...
- 【★】KMP算法完整教程
KMP算法完整教程 全称: Knuth_Morris_Pratt Algorithm(KMP算法) 类型: ...
- 【★】KMP算法完整教程
KMP算法完整教程 全称: Knuth_Morris_Pratt Algorithm(KMP算法) 类型: ...
- KMP算法完整教程 (上)
KMP算法完整教程 全称: Knuth_Morris_Pratt Algorithm(KMP算法) 类型: 高级检索算法 功能: 字符串匹配查找 提出者: D.E.Knuth(克努兹),J.H.Mor ...
- !KMP算法完整教程
KMP算法完整教程 全称: Knuth_Morris_Pratt Algorithm(KMP算法) 类型: ...
- 【HNOI 2019】JOJO
Problem Description JOJO 的奇幻冒险是一部非常火的漫画.漫画中的男主角经常喜欢连续喊很多的「欧拉」或者「木大」. 为了防止字太多挡住漫画内容,现在打算在新的漫画中用 \(x\) ...
- 从有限状态机的角度去理解Knuth-Morris-Pratt Algorithm(又叫KMP算法)
转载请加上:http://www.cnblogs.com/courtier/p/4273193.html 在开始讲这个文章前的唠叨话: 1:首先,在阅读此篇文章之前,你至少要了解过,什么是有限状态机, ...
- 笔试算法题(52):简介 - KMP算法(D.E. Knuth, J.H. Morris, V.R. Pratt Algorithm)
议题:KMP算法(D.E. Knuth, J.H. Morris, V.R. Pratt Algorithm) 分析: KMP算法用于在一个主串中找出特定的字符或者模式串.现在假设主串为长度n的数组T ...
- [Algorithm] 字符串匹配算法——KMP算法
1 字符串匹配 字符串匹配是计算机的基本任务之一. 字符串匹配是什么?举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串& ...
随机推荐
- gwt 创建 超链接cell (HyperTextCell)
package com.cnblogs.hooligen.client; import com.google.gwt.cell.client.AbstractCell; import com.goog ...
- javascript高级编程笔记03(正则表达式)
引用类型 检测数组 注:我们实际开发中经常遇到要把数组转化成以逗号隔开,我以前都是join来实现,其实又更简单的方法可以用toString方法,它会自动用逗号隔开转换成字符串,其实toString内部 ...
- ECSHOP安装或使用中提示Strict Standards: Non-static method cls_image:
随着ECSHOP的不断发展,越来越多的人成为了ECSHOP的忠实粉丝.由于每个人的服务器环境和配置都不完全相同,所以ECSHOP也接二连三的爆出了各种各样的错误信息.相信不少新手朋友在ECSHOP安装 ...
- Python/Numpy大数据编程经验
Python/Numpy大数据编程经验 1.边处理边保存数据,不要处理完了一次性保存.不然程序跑了几小时甚至几天后挂了,就啥也没有了.即使部分结果不能实用,也可以分析程序流程的问题或者数据的特点. ...
- 《暗黑世界GM管理后台系统》部署+功能说明
原地址:http://blog.csdn.net/uxqclm/article/details/11969761 欢迎来到9秒:www.9miao.com 暗黑三国管理后台说明文档 (一)功能描述该后 ...
- ***微信浏览器禁止app下载链接怎么办
通过扫描二维码下载APP已成为一个非常方便的方式,微信也成为扫描二维码重要的工具,但是扫描后微信浏览器会对APK和appStore的链接进行屏蔽,导致用户无法正常下载.本文提供两个迂回的解决方案:1. ...
- POJ 3321 Apple Tree(树状数组)
点我看题目 题意 : 大概是说一颗树有n个分岔,然后给你n-1对关系,标明分岔u和分岔v是有边连着的,然后给你两个指令,让你在Q出现的时候按照要求输出. 思路 :典型的树状数组.但是因为没有弄好数组 ...
- Java中对List集合的排序
方法一: 第一种方法,就是list中对象实现Comparable接口,代码如下: 实体类: public class Person implements Comparable<Person> ...
- configure文件中判断某函数或库是否存在的一个方法
echo " #include<stdio.h> #include<openssl/ssl.h> int main() { return 0; } " &g ...
- QT带OpenGL与不带的区别,QT5是一个伟大的框架,短时期内根本不会有替代者
你好 , 我Qt的初学者 , 我在官网下载Qt时感觉很迷茫 , 不知道要下载哪个, 麻烦你写他们之间的不同点:Qt 5.2.0 for Windows 32-bit (MinGW 4.8, OpenG ...