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算法的更多相关文章

  1. c++程序员必知的几个库

    c++程序员必知的几个库 1.C++各大有名库的介绍——C++标准库 2.C++各大有名库的介绍——准标准库Boost 3.C++各大有名库的介绍——GUI 4.C++各大有名库的介绍——网络通信 5 ...

  2. 迈向高阶:优秀Android程序员必知必会的网络基础

    1.前言 网络通信一直是Android项目里比较重要的一个模块,Android开源项目上出现过很多优秀的网络框架,从一开始只是一些对HttpClient和HttpUrlConnection简易封装使用 ...

  3. 程序员必知的8大排序(三)-------冒泡排序,快速排序(java实现)

    程序员必知的8大排序(一)-------直接插入排序,希尔排序(java实现) 程序员必知的8大排序(二)-------简单选择排序,堆排序(java实现) 程序员必知的8大排序(三)-------冒 ...

  4. 程序员必知的8大排序(二)-------简单选择排序,堆排序(java实现)

    程序员必知的8大排序(一)-------直接插入排序,希尔排序(java实现) 程序员必知的8大排序(二)-------简单选择排序,堆排序(java实现) 程序员必知的8大排序(三)-------冒 ...

  5. 程序员必知的8大排序(一)-------直接插入排序,希尔排序(java实现)

    http://blog.csdn.net/pzhtpf/article/details/7559896 程序员必知的8大排序(一)-------直接插入排序,希尔排序(java实现) 程序员必知的8大 ...

  6. 值得花费一周研究的算法 -- KMP算法(indexOf)

    KMP算法是由三个科学家(kmp分别是他们名字的首字母)创造出来的一种字符串匹配算法. 所解决的问题: 求文本字符串text内寻找第一次出现字符串s的下标,若未出现返回-1. 例如 text : &q ...

  7. [置顶] 程序员必知(三):一分钟知道URI编码(encodeURI)

    因为浏览器会用一些特殊的字符作为特定的意义,所以在要传输的内容上如果有这些特殊的字符的话,就需要对其进行转义才能正确传输,如以下字符为发送时候的关键字,即特殊字符 ;/?:@&=+$,# 所以 ...

  8. 数据结构与算法--KMP算法查找子字符串

    数据结构与算法--KMP算法查找子字符串 部分内容和图片来自这三篇文章: 这篇文章.这篇文章.还有这篇他们写得非常棒.结合他们的解释和自己的理解,完成了本文. 上一节介绍了暴力法查找子字符串,同时也发 ...

  9. Android程序员必知必会的网络通信传输层协议——UDP和TCP

    1.点评 互联网发展至今已经高度发达,而对于互联网应用(尤其即时通讯技术这一块)的开发者来说,网络编程是基础中的基础,只有更好地理解相关基础知识,对于应用层的开发才能做到游刃有余. 对于Android ...

  10. 程序员必知的8大排序(四)-------归并排序,基数排序(java实现)

    程序员必知的8大排序(一)-------直接插入排序,希尔排序(java实现) 程序员必知的8大排序(二)-------简单选择排序,堆排序(java实现) 程序员必知的8大排序(三)-------冒 ...

随机推荐

  1. AutoCAD LT 2019 安装教程

    autocad lt 2019是mac平台上一款全球领先的更快.更精确地创建二维图形设计平台,用于二维草图.图形和文档编制,广泛应用于机械设计.工业制图.工程制图.土木建筑.装饰装潢.服装加工等多个行 ...

  2. IDEA中Git的更新、提交、还原方法

    第一步:在提交项目之前必须先对项目进行更新,此项特别重要,如果不进行更新,别人有项目提交到服务器上,那么你的项目将会提交不上去,使用git解决冲突会比较麻烦,即使你解决了冲突,但是有时候不注意会冲掉别 ...

  3. replace用法替换实例

    实例一: 待处理字符串:str="display=test name=mu display=temp" 要求:把display=后的值都改成localhost JS处理方法: st ...

  4. Appium+python 使用 press_keycode 如何输入大写字母

    背景:在做自动化测试项目时,需要在文本框中输入一串数字和字母组合的字符串(注:此页面为webview无法使用send_keys方法) 要使用send_keys方法首先要知道键盘字符对应的数值,这个可以 ...

  5. autoit脚本-从基本的函数用法开始

    适配浏览器:目前了解的有ie浏览器 MsgBox 显示可选提示超时的消息框 _ArrayDisplay _arraydisplay($aArray)  ;$aArra一般为数组,方法用于展示表格展示数 ...

  6. hdfs性能调优(cloudera)

    参照官方文档:http://www.cloudera.com/content/cloudera/en/documentation/core/latest/topics/cdh_ig_yarn_tuni ...

  7. oracle 审计功能

    Oracle 11g推出了审计功能,但这个功能会针对很多操作都产生审计文件.aud,日积月累下来这些文件也很多,默认情况下,系统为了节省资源,减少I/0操作,其审计功能是关闭的 一.审计功能关闭 1. ...

  8. webform运行时弹出JavaScript的alert窗口

    https://stackoverflow.com/questions/9720143/asp-net-web-application-message-box Or create a method l ...

  9. Python中的反转字符串问题

    按单词反转字符串是一道很常见的面试题.在Python中实现起来非常简单. def reverse_string_by_word(s): lst = s.split() # split by blank ...

  10. shell 按行读取文件的内容

    test.py: #coding=utf- import subprocess compilePopen = subprocess.Popen('gcc haha',shell=True,stderr ...