关于"从头到尾彻底理解KMP(2014年8月22日版)"的个人理解
来源:互联网 发布:故宫淘宝是什么 编辑:程序博客网 时间:2024/06/04 19:09
从头到尾彻底理解KMP(2014年8月22日版)
1,此文先求解next数组
这里先从直观上来理解,即考虑模式串P的“各个子串的前缀后缀的公共元素的最大长度”容易得到,然后通过右移“各个子串的前缀后缀的公共元素的最大长度”数组,然后p0补-1得到next数组。
之后通过代码求解next数组的各个元素的值。
这里需要弄明白为什么需要递归,为什么可以递归求解?
递归通过关键代码
<span style="font-size:14px;">k=next[k]</span>实现。因为我们不希望用最笨、最原始、浪费时间、浪费感情的回溯法来进行模式串和目标串的匹配,所以用到了next数组来帮助我们找到一个合适的、合理的、恰当的目标串的相同前缀后缀位置,这就是next数组存在的意义。
而如果当前p[j]位置的元素!=p[k]位置的元素了,那么我们需要知道从紧邻p[j]位置之前符合要求的后缀串中再找到最长匹配后缀串,而紧邻p[j]位置之前符合要求的后缀串与紧邻p[k]位置之前符合要求的后缀串是一样的,所以我们可以将问题转化为从紧邻p[k]位置之前符合要求的后缀串中再找到最长匹配后缀串,这样就形成了递归的形式。
同时也回答了“为什么需要递归,为什么可以递归求解?”这两个问题。
2,然后对next数组进行优化
这里首先要理解不能允许p[j] == p[ next[j] ]的含义:之前我们都在讨论next数组的求解问题,这里问题升华了,我们要做到避免p[j] (模式串)和 s[i](目标串) 匹配失败的情况,这样就少了很多不必要的操作步骤,从而节省了时间,提高了效率。
我们用原文中的例子来解释这个事情:
比如,如果用之前的next 数组方法求模式串“abab”的next 数组,可得其next 数组为-1 0 0 1(0 0 1 2整体右移一位,初值赋为-1),当它跟下图中的文本串去匹配的时候,发现b跟c失配,于是模式串右移j - next[j] = 3 - 1 =2位。
右移2位后,b又跟c失配。事实上,因为在上一步的匹配中,已经得知p[3] = b,与s[3] = c失配,而右移两位之后,让p[ next[3] ] = p[1] = b 再跟s[3]匹配时,必然失配。问题出在哪呢?
问题出在不该出现p[j] == p[ next[j] ]。为什么呢?理由是:当p[j] != s[i] 时,下次匹配必然是p[ next [j]] 跟s[i]匹配,如果p[j] = p[ next[j] ],必然导致后一步匹配失败(因为p[j]已经跟s[i]失配,然后你还用跟p[j]等同的值p[next[j]]去跟s[i]匹配,很显然,必然失配),所以不能允许p[j] = p[ next[j ]]。如果出现了p[j] = p[ next[j] ]咋办呢?如果出现了,则需要再次递归,即令next[j] = next[ next[j] ]。
因为原next数组的求解算法中,未考虑p[j] == p[ next[j] ]的情况,而是直接令next[j] = k,虽然算法没有错误,但是这里是可以改进的,即将p[j] (模式串)和 s[i](目标串) 匹配失败而引起的递归的情况在next数组构建时提前考虑到,也就是通过改进next数组元素的值来节省后续的很多步骤,提高了效率。后来的时间复杂度可以说明KMP效率还是很高的~
3,将next数组用于目标串的匹配
这里就没什么好说的。
4,分析KMP算法的时间复杂度
有了算法代码,容易得到结果。
5,介绍两种扩展算法
BM算法虽然一直都在说模式串怎么怎么样,实质还是基于模式串和目标串的匹配对比操作,无论是坏字符还是好后缀都是这样,但是这个算法确实构思巧妙,很是牛逼!
该算法从模式串的尾部开始匹配,且拥有在最坏情况下O(N)的时间复杂度。在实践中,比KMP算法的实际效能高。
我们已经介绍了KMP算法和BM算法,这两个算法在最坏情况下均具有线性的查找时间。
但实际上,KMP算法并不比最简单的c库函数strstr()快多少,而BM算法虽然通常比KMP算法快,但BM算法也还不是现有字符串查找算法中最快的算法,比BM算法更快的查找算法即Sunday算法。
- 关于"从头到尾彻底理解KMP(2014年8月22日版)"的个人理解
- 从头到尾彻底理解KMP(2014年8月22日版)
- 从头到尾彻底理解KMP(2014年8月22日版)
- 从头到尾彻底理解KMP(2014年8月22日版)
- [置顶] 从头到尾彻底理解KMP(2014年8月22日版)
- 从头到尾彻底理解KMP(2014年8月22日版)
- [置顶] 从头到尾彻底理解KMP(2014年8月22日版)
- 从头到尾彻底理解KMP(2014年8月22日版)
- 从头到尾彻底理解KMP(2014年8月22日版)
- 从头到尾彻底理解KMP(2014年8月22日版)
- 从头到尾彻底理解KMP(2014年8月22日版)
- 从头到尾彻底理解KMP(2014年8月22日版)
- 从头到尾彻底理解KMP(2014年8月22日版)
- 从头到尾彻底理解KMP(2014年8月22日版)
- 从头到尾彻底理解KMP(2014年8月22日版)
- 从头到尾彻底理解KMP(2014年8月22日版)
- 从头到尾彻底理解KMP(2014年8月22日版)(转载)
- 从头到尾彻底理解KMP(2014年8月22日版)
- 第一周项目 程序阅读——初识对象 1.1
- Android访问网络,使用HttpURLConnection还是HttpClient?
- POJ1330.Nearest Common Ancestors——最近公共祖先(dfs+ST在线算法)
- 强制关机,导致Eclipse启动加载Loading workbench无响应
- oracle 备份
- 关于"从头到尾彻底理解KMP(2014年8月22日版)"的个人理解
- POJ 2318 TOYS(计算几何)
- java贪吃蛇
- GPL LGPL Apache2.0 BSD 开源协议扫盲帖
- openssl 用法例子PKCS7解析
- bcp sqlcmd bulkinsert中unicode问题,Unexpected EOF encountered in BCP data-file
- vector,map,list,queue区别--总结的不错
- 使用asw sdk 开发java
- Android studio导入第三方开源库方法