程序员必会算法-KMP算法
KMP算法是一种优秀的字符串匹配算法,字符串匹配的常规算法是一步一步进行移位和比较操作,直至找到完全相匹配的字符串。
下面通过一个例子,为大家仔细说明KMP算法的使用和思路:
问题:
在字符串“DEABCDABABCDABCDABDE”字符串中,匹配字符串"ABCDABD".
算法思路:
KMP算法的思路在于,根据已经匹配的部分字符的信息,不把搜索位置移回已经比较过的位置,这样就提高了效率,是不是还是有点不清楚?没关系,让我们来根据一个例子来切实体会一下KMP算法是如何实现的。
图解:
1、KMP算法的核心是一张“部分匹配表”,这个表是怎么来的,后面再说,先用了再说,下图就是该问题的部分匹配表。

这个表上面一行是我们的模式字符串,下面一行是每个字符所对应的匹配值
移位规则是 移动位数 = 已匹配的字符串长度 - 已匹配字符串的最后一位字符所对应的匹配值。
2、接下来就开始进行操作

上图中我们看到,移位两位后,我们找到了部分匹配的字符串"ABCDAB",但并没有找到完全匹配的字符串,如果是常规思路,就是在继续往下一步一步移位,但我们这里不这样进行,我们观察到,已经匹配的字符串长度是6,匹配到的最后一个字符是"B",查询部分匹配表,这个“B”的部分匹配值是2,那么根据我们算法的移位规则,下一步我们的移位长度 = 6 - 2 = 4;
3、

╮(╯▽╰)╭,有没有发现,移了4位之后,刚好到达了下一个“AB”处?是不是很神奇?好了,打住,我们继续往下移,当前已匹配的字符串长度为2,查询这个“B”的匹配值为0(别和上个B搞混了),根据算法,我们接下来移位长度是 2 - 0 = 2;
4、

继续,和前面的步骤相同,我们这次移位长度为 6 - 2 = 4;
5、

至此,我们已经找到了完全匹配的字符串,当然,如果母字符串的长度较长,我们可以继续进行移位,继续寻找,和之前的步骤相同,下次我们移位长度为 7 - 0 = 7。
算法分析:
不知道大家看到现在,有没有一点明悟?来,让我们分析一下模式字符串“ABCDABD”:
对于搜索来说,我们首先关注的肯定是第一个字符,如果第一个字符都不匹配,那么后面的字符就没有比较的必要了,该目标字符串的第一个字符是’A‘,让我们看看这个字符串里有没有’A‘,诶,还真有,假如说我们现在已经匹配了“ABCDA”,5个字符,我们要移4位才能从第一个'A'移到第二个'A',’A‘只有一个字符,5 - 1 = 4;
再往下看,关注完第一个字符,我们开始关注和第一个字符依次相连的子字符串,这些字符串有一个共性,就是第一个字符都是’A‘,那我们看看这种字符串能有多少,"AB","ABC","ABCD","ABCDA","ABCDAB","ABCDABD",再看看这些字符串在目标字符串“ABCDABD”中存在几个,可以看出,除去和第一个“A”相连的,“AB”还有一个,其余的没有,而"AB"长度为2,所以在表中,第二个B的匹配值为2。
该算法的核心思路在于,有时候,字符串的头部和尾部可能会有重复。
不知道大家有没有听懂?让我们把匹配字符串换一下,换成“ABCDABC”,现在的部分匹配表应该是:

算法思考和延伸:
如果模式字符串过长,部分匹配表的生成会占用较多的时间,如何去提高部分匹配表的生成效率,是该算法的优化所在。(个人观点,如有大佬,请指教!)
该算法思想和字典编码有一定的相通之处。改天我会写出一个字典编码的文章。敬请期待!
程序员必会算法-KMP算法的更多相关文章
- c++程序员必知的几个库
c++程序员必知的几个库 1.C++各大有名库的介绍——C++标准库 2.C++各大有名库的介绍——准标准库Boost 3.C++各大有名库的介绍——GUI 4.C++各大有名库的介绍——网络通信 5 ...
- 迈向高阶:优秀Android程序员必知必会的网络基础
1.前言 网络通信一直是Android项目里比较重要的一个模块,Android开源项目上出现过很多优秀的网络框架,从一开始只是一些对HttpClient和HttpUrlConnection简易封装使用 ...
- 程序员必知的8大排序(三)-------冒泡排序,快速排序(java实现)
程序员必知的8大排序(一)-------直接插入排序,希尔排序(java实现) 程序员必知的8大排序(二)-------简单选择排序,堆排序(java实现) 程序员必知的8大排序(三)-------冒 ...
- 程序员必知的8大排序(二)-------简单选择排序,堆排序(java实现)
程序员必知的8大排序(一)-------直接插入排序,希尔排序(java实现) 程序员必知的8大排序(二)-------简单选择排序,堆排序(java实现) 程序员必知的8大排序(三)-------冒 ...
- 程序员必知的8大排序(一)-------直接插入排序,希尔排序(java实现)
http://blog.csdn.net/pzhtpf/article/details/7559896 程序员必知的8大排序(一)-------直接插入排序,希尔排序(java实现) 程序员必知的8大 ...
- 值得花费一周研究的算法 -- KMP算法(indexOf)
KMP算法是由三个科学家(kmp分别是他们名字的首字母)创造出来的一种字符串匹配算法. 所解决的问题: 求文本字符串text内寻找第一次出现字符串s的下标,若未出现返回-1. 例如 text : &q ...
- [置顶] 程序员必知(三):一分钟知道URI编码(encodeURI)
因为浏览器会用一些特殊的字符作为特定的意义,所以在要传输的内容上如果有这些特殊的字符的话,就需要对其进行转义才能正确传输,如以下字符为发送时候的关键字,即特殊字符 ;/?:@&=+$,# 所以 ...
- 数据结构与算法--KMP算法查找子字符串
数据结构与算法--KMP算法查找子字符串 部分内容和图片来自这三篇文章: 这篇文章.这篇文章.还有这篇他们写得非常棒.结合他们的解释和自己的理解,完成了本文. 上一节介绍了暴力法查找子字符串,同时也发 ...
- Android程序员必知必会的网络通信传输层协议——UDP和TCP
1.点评 互联网发展至今已经高度发达,而对于互联网应用(尤其即时通讯技术这一块)的开发者来说,网络编程是基础中的基础,只有更好地理解相关基础知识,对于应用层的开发才能做到游刃有余. 对于Android ...
- 程序员必知的8大排序(四)-------归并排序,基数排序(java实现)
程序员必知的8大排序(一)-------直接插入排序,希尔排序(java实现) 程序员必知的8大排序(二)-------简单选择排序,堆排序(java实现) 程序员必知的8大排序(三)-------冒 ...
随机推荐
- python3之platform模块
platform模块可以获取操作系统的相关信息. >>> platform.system() #获取系统名称 'Linux' >>> platform.archit ...
- javascript实现继承的三种方式
一.原型链继承 function Parent(){} function Child(){} Child.prototype = new Parent(); 通过对象child的prototype属 ...
- Mysql索引使用解析
摘自:http://blog.chinaunix.net/uid-25063573-id-3032578.html Mysql索引使用解析 1.索引作用 在索引列上,除了上面提到的有序查找之外,数据库 ...
- GreenDao教程2
总述: 所有的增删改查都需要通过greendao通过实体对象类生成的Dao来实现, 具体实现如下图 1.初始化数据库操作对象(GreenDao自动生成的操作对象) 2.通过数据库操作对象,进行增删改查 ...
- bootstrap:modal & iframe
form提交绑定到特定的iframe & form的结果在dialog上显示 form:target属性 <!-- when the form is submitted, the ser ...
- Thinkphp5背景图片的引入~ 以及图片的引入
将图片信息从数据库查询 再渲染于前台页面
- 数据类型 varchar 和 uniqueidentifier 在 add 运算符中不兼容
select '<a href="/'+a.id +'" title="'+ a.title +'">'+a.Title+'</a>' ...
- python实现将base64编码的图片下载到本地
# -*- coding:utf-8 -*- #!python3 import os import base64 sss ="""base64的编码"" ...
- centos7中bash: maven: 未找到命令... 解决办法
安装了maven,但在执行mvn -v或maven-versions时提示bash: maven: 未找到命令... 应该是环境变量出错,把MAVEN_HOME的路径换到PATH上就可以了,如下: e ...
- Inquirer.js
一个使用界面进行交互的命令行集合 4.0以上的版本只支持node 6以上的,node4请使用3.x 目标和理念(hilosophy) 努力去做一个容易的 嵌入式的(embeddable) 和优美的命令 ...