(原创)白话KMP算法详解
引子:BF暴力算法
KMP算法知名度相当高,燃鹅其理解难度以及代码实现对于初学数据结构和算法的同学并不友好,经过两天的总结,详细总结KMP算法如下:
初学串的模式匹配时,我们都会接触到,或者说应该能想到作为教学引子的BF暴力算法,那么先来简单了解一哈:
我有一个大串是"abccabca",小串是"bca",现在要找到小串在大串中的位置,战斗开始
①
②
③
④
⑤
⑥
⑦
⑧
这个算法理解起来肥肠简单,我在这里假定 i 指针指向大串(主串)的首地址,j 指针指向小串(模式串)的首地址。首先大串第一位正面对比小串第一位,两元素若相等,则两指针分别后移,继续比较第二位。那么这个算法被称为暴力算法的原因就在于当两串元素对比不相等时,j指针就会回溯到小串的首地址,这本无可厚非,而i指针却会回溯到对比之初的后一位,比如上述第四步大小串匹配不上之后i指针马上来到了第三位,导致了完全无用的第五和第六步比较,造成了算法时间复杂度的加大,而且主串元素数嵌套小串元素数的两重循环,直接造成了O(m*n)的人间大惨案。虽然能实现模式匹配,但是我们的D.E.Knuth、J.H.Morris和V.R.Pratt觉得这个算法有必要改进一哈(V.R.Pratt:嘤嘤嘤),而且出于科学家的身份和*友情缘,三位同时研究出了一个船(全)新的匹配方式,KMP算法横空出世,当然只要体验三分钟,你就会跟我当时一样,放弃这个算法。
附:BF暴力算法代码(取自《大话数据结构》 ps: S[0]、T[0]表示该串的长度)
第一章:kmp算法
黄历上写明了,这个算法不宜先学代码,否则可能会造成理解困难。我这里还是先以一个例子来讲解一下这三个外国同学的算法:
(例子取自《大话数据结构》)
不难发现,我们的模式串没有一个字母是重复出现的,而第一步已经确诊主串和模式串的前五位一模一样,所以你如果这时候使用BF暴力算法,依次用主串的第二位到第五位跟模式串的首位正面刚,就是人傻劲大,完全莫得必要。所以我们要想个办法避免这种重复浪费的现象,结合上面的BF例子,我们也可以明白,这种现象的出现并非是 j 指针的错,而是 i 指针作为主串的指针瞎回溯造成的匹配浪费。
好的,理解了上面的步骤为啥子是多余的,我们再次征讨一下曾被我们用了很长一段时间的暴力算法,正因为它能力有限,只能通过把 i 回溯到一个很靠前的位置才能实现匹配,重点来了,这时来了一个叫做KMP的人,告诉你BF能做到的他也能做到,甚至能把时间复杂度降为O(m+n),这个时间复杂度是什么概念,意味着 i 再也不用承受眼看着无用还不得不回溯的命运。我们来看看KMP算法是怎样干掉BF这个老黄牛的。(前方高能,佩戴脑子食用效果更佳)
要想 i 值不回溯,就一定要在 j 上面做文章,我们再次看看上面的例子,如果第一步刚发现 i=6 两串不匹配时,摁住 i 指针,让 i 继续=6 ,然后这时候使j指针回到初始的位置,即 i = 6 时 j = 1,让主串中的 f 和模式串的 a 比较,就很完美辽,那这里也可能有机智的同学问,要是我的模式串中出了一个和首元素相等的元素怎么破?(/手动狗头),不妨看看这个例子,主串是 "abcabcabx", 模式串是 "abcabx" ,当然贼符合你的心意,当用BF第一轮比到第六位,发现 c 和 x 不一样,这时你会想,把 i 回溯到第四个元素(即 a),再用 j = 1 直接就出结果。但是你想一想,可否不移动 i ,让 j = 3 直接匹配,况且这个例子只是特殊情况,所以怎样看来都是不必回溯 i 的,下面我们看看怎样让 j 发挥他的作用。
既然是 j 的事,就和主串没关系了,我们来研究一下上一段这个例子,我们刚才为什么要移动 j 让他等于3,为了省去模式串前面存在的重复比较,这个重复比较是哪来的呢,就在于 模式串结构中的前后重复程度, "abcabx"这个例子中的串可以分为 "a"+"bcabx" 、"ab"+"cabx"、"abc"+"abx"、"abca"+"bx"、"abcab"+"x",前缀有"a"、"ab"、"abc"、"abca"、"abcab",定义第一个前缀重复度为0,第二个前缀重复度为1,第三个也是1,第四个我们不难发现首尾呼应,所以他的重复度较前面的加一是2,最后一个前缀ab段重复,故重复度为3。
那我们求出这个重复度有毛用呢,我们再看看那个例子,当我们在第一轮发现第六个不相等时,我们可以发现前五位重复度为3,这个3眼熟不,他可以直接在 i 不回溯的前提下把 j 带到正确的位置,即 j = 3,那我们模式串的每一个数都需要这个值来实现KMP算法,我们用一个 next[x] 数组来储存这些数,至于x的大小取决于你的模式串长度。
这时候我们来看看KMP算法的代码(当然还是来自《大话数据结构》的伪码):
这段代码是获得 next数组 的
敲了芥末多的字,希望大家可以快速理解这个KMP模式匹配算法,未完待续.......
预告第二章:KMP算法的改进版本
届时神秘的nextval数组将浮现江湖
continued
(原创)白话KMP算法详解的更多相关文章
- KMP算法详解(转自中学生OI写的。。ORZ!)
KMP算法详解 如果机房马上要关门了,或者你急着要和MM约会,请直接跳到第六个自然段. 我们这里说的KMP不是拿来放电影的(虽然我很喜欢这个软件),而是一种算法.KMP算法是拿来处理字符串匹配的.换句 ...
- kmp算法详解
转自:http://blog.csdn.net/ddupd/article/details/19899263 KMP算法详解 KMP算法简介: KMP算法是一种高效的字符串匹配算法,关于字符串匹配最简 ...
- [转] KMP算法详解
转载自:http://www.matrix67.com/blog/archives/115 KMP算法详解 如果机房马上要关门了,或者你急着要和MM约会,请直接跳到第六个自然段. 我们这里说的K ...
- 算法进阶面试题01——KMP算法详解、输出含两次原子串的最短串、判断T1是否包含T2子树、Manacher算法详解、使字符串成为最短回文串
1.KMP算法详解与应用 子序列:可以连续可以不连续. 子数组/串:要连续 暴力方法:逐个位置比对. KMP:让前面的,指导后面. 概念建设: d的最长前缀与最长后缀的匹配长度为3.(前缀不能到最后一 ...
- 数据结构4.3_字符串模式匹配——KMP算法详解
next数组表示字符串前后缀匹配的最大长度.是KMP算法的精髓所在.可以起到决定模式字符串右移多少长度以达到跳跃式匹配的高效模式. 以下是对next数组的解释: 如何求next数组: 相关链接:按顺序 ...
- KMP算法详解&&P3375 【模板】KMP字符串匹配题解
KMP算法详解: KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt(雾)提出的. 对于字符串匹配问题(such as 问你在abababb中有多少个 ...
- KMP算法详解-彻底清楚了(转载+部分原创)
引言 KMP算法指的是字符串模式匹配算法,问题是:在主串T中找到第一次出现完整子串P时的起始位置.该算法是三位大牛:D.E.Knuth.J.H.Morris和V.R.Pratt同时发现的,以其名字首字 ...
- 字符串匹配KMP算法详解
1. 引言 以前看过很多次KMP算法,一直觉得很有用,但都没有搞明白,一方面是网上很少有比较详细的通俗易懂的讲解,另一方面也怪自己没有沉下心来研究.最近在leetcode上又遇见字符串匹配的题目,以此 ...
- <转>KMP算法详解
看了好久的KMP算法,都一直没有看明白,直到看到了这篇博客http://www.tuicool.com/articles/e2Qbyyf让我瞬间顿悟. 如果你看不懂 KMP 算法,那就看一看这篇文章 ...
随机推荐
- oracle之DQL
一.单表查询 语法:select * from table where 条件 group by 分组 having 过滤分组 order by 排序 --查询平均工资低于2000的部门的最大工资和平均 ...
- IOS 枚举 enum
前言:oc中枚举的正确使用,可以增强代码的可读性,减少各种“错误”,让代码更加的规范.下面先介绍枚举的用法,最后介绍个人对枚举的理解,什么是枚举,为什么用枚举. 一. OC中,枚举的使用 1. 写法1 ...
- Swift_类和结构体
Swift_类和结构体 点击查看源码 struct Resolution { var width = 0 var height = 0 } class VideoMode { var resoluti ...
- Java九阳真经论述及愿景
Java九阳真经论述及愿景 “他强由他强,清风拂山冈,他横由他横,明月照大江.” <倚天屠龙记>中张无忌被玄冥二老的玄冥神掌打伤后,体寒难耐,到处求解决之法.一次被韦蝠王打下山谷后,偶遇一 ...
- chromium之message_pump_win之二
接下来分析 MessagePumpForUI上一篇分析MessagePumpWin,可以参考chromium之message_pump_win之一 根据对MessagePumpWin的分析,Messa ...
- Sass使用
1. 什么是Sass ??? Sass是一个将脚本解析成CSS的脚本语言,也可以称为CSS扩展语言. 2. 安装: 第一步:先安装Ruby (sass基于Ruby语言开发而成,因此安装sass前需 ...
- json提取嵌套数据
//数据 string html = "{\"code\":\"0000\",\"desc\":\"\",\& ...
- tp3.2源码解析——入口文件
如果有人读这篇文章并跟着做的话,希望你能使用支持函数跳转的编辑器,还要善用var_dump和exit,对着源码去调试着看.跟着入口文件读,执行到哪里你看到哪里,对于那些不能一眼看出来的配置,则要记录下 ...
- php ecshop 二级域名切换跳转时session不同步,解决session无法共享同步导致无法登陆或者无法退出的问题
echshop基础上做了单点登录的 一级域名与二级域名 退出时 清空session 都是一级域名的session 因为二级域名的session是设置在二级域名上的 echshop基础上没有做单点登录的 ...
- laravel4.2 union联合,join关联分组查询最新记录时,查询条件不对,解决方案
需求: 分组联合查询,或者最新记录. 问题: mysql分组的时候默认会查询第一条记录,存在gourp by时 order by 无效. 一般解决办法就是 ,select * from ( sele ...