KMP算法的细节问题
preface:
想必,很多人都知道D.E.Knuth与V.R.Pratt和J.H.Morris同时提出所谓的狂拽酷炫屌炸天的KMP算法,在对字符串的匹配(或是字符串的查找)方面表现出比较好的效率,该算法对Brute-Force算法的较大改进,具体地讲就是消除了主串指针的回溯,从而使匹配的时间复杂度从O(N2)降低到O(N+M)(N为文本串的长度,M为模式串长度)。其传神之处在于在于针对模式串构造的一个Nest[]数组(该数组只与模式串有关)。
keyword:
KMP算法、增强KMP算法
(扯完了蛋,进入主题。)
Q1:前缀字符串与后缀字符串
A:对于某一字符串来说,约定从第一个字符开始向后的连续若干长度的字符串为前缀字符串,同理从最后一个字符开始向前的连续若干长度的字符串为后缀字符串
case 1:对于字符串“qcer”而言,”qc“为长度为2的前缀字符串,”er“为长度为2的后缀字符串。特殊的,“qcer”既是前缀字符串又是后缀字符串。
Q2:Nest[]数组为何物?
A:Nest[k]定义为在模式串中下标为K位置的前面所有字符串中所有前缀字符串与后缀字符串相等的情况中最长的匹配长度。but,如这等让你我眩晕的表达,不看也罢!一图胜前言!
对于Nest[2],下标为2即字符‘c’前面的字符串为“ca”,故没有前缀字符串与后缀字符串相等的情况,其值当然为0。
对于Nest[3],下标为3即字符‘l’前面的部分为“cac”,故只有前缀字符串“c”与后缀字符串“c”,其值为1。
其实这个空降的Nest[]数组是有点不好理解的,至少理解很不深刻!
So,下面再给出一种通用的理解方式:
对于求Nest[7]的值,更直观的过程可以如下图。
即把字符串下标为7即字符‘m’之前的字符串“cacldca”从右往左部逐步推进,整个过程在步骤2位置取得正确的值2。步骤3到步骤6中任意一步重叠部分均不能完全匹配(如果有重叠部分完全匹配的情况,那么必然其值比2大)。故不能取到比2更大的值。
首先,理解这个过程度对后面核心算法的匹配过程相当重要。其次,真正求Nest[]数组的值当然不会用这样low的方法。
如果匹配的过程看做模式串从主串的开始处向右”移动“+匹配的过程,那么KMP不在只是逐步移动,而且还能”跨越式“移动。
Q3:KMP算法为什么能实现”跨越式“移动的原理?
A:先上图!
位置1中,n和m不等,直接跨越过4个字符到位置2处,中间都不用比较就知道不会有匹配成功情况。但是为什么可以这样?再上图!
因为在位置3到位置6之间绝对不会出现重叠部分相匹配的情况,如果出现那么Nest[7]的值将定会是一个比2大的数,这与Nest[]的定义是相悖的,所以处理3到6的步骤可以自信地跨越!!
Q4:Nest[]数组酷炫的解法?
A:还是上图!
k为位置j的最长前、后缀匹配串3的下一个位置,同理,m为k的最长前、后缀匹配串1的下一个位置。
Nest[j]已知,即对j位置前面的所有串,前缀串3和后缀串4相等且最长;k在j前面,Nest[k]也已知,同理,k前面的所有串,前缀串1和后缀串2相等且最长。
求Nest[i]分两种情况:
1) arr[k] = arr[j];Nest[i] = Nest[j]+1;这是显然的。
2) arr[k] != arr[j];
这时需要我们稍作分析:因为串3=串4,串1=串2,对应必然有,串5=串6,所以必有,串1=串2=串5=串6。
到目前为止由已知只能推出串1=串6,所以,在此基础上尝试扩展串,即判断arr[m]是否等于arr[j]。此时又分情况两种情况:
1) arr[m = arr[j];Nest[i] = Nest[m]+1;这是显然的。
2) arr[m != arr[j];以此方式一直推导下去!
没错,递归求解是正解!时间复杂度O(m)(m为模式串长度)。
Code:
KMP算法的细节问题的更多相关文章
- 通过图片对比带给你不一样的KMP算法体验
KMP 算法,俗称“看毛片”算法,是字符串匹配中的很强大的一个算法,不过,对于初学者来说,要弄懂它确实不易. 笔者认为,KMP 算法之所以难懂,很大一部分原因是很多实现的方法在一些细节的差异.体现在几 ...
- (原创)详解KMP算法
KMP算法应该是每一本<数据结构>书都会讲的,算是知名度最高的算法之一了,但很可惜,我大二那年压根就没看懂过~~~ 之后也在很多地方也都经常看到讲解KMP算法的文章,看久了好像也知道是怎么 ...
- KMP 算法总结
KMP算法是基本的字符串匹配算法,但是代码实现上有一些细节容易错.这篇随笔将认真总结一下. KMP算法的核心是: The KMP algorithm searches for occurrences ...
- KMP算法&next数组总结
http://www.cnblogs.com/yjiyjige/p/3263858.html KMP算法应该是每一本<数据结构>书都会讲的,算是知名度最高的算法之一了,但很可惜,我大二那年 ...
- 【★】KMP算法完整教程
KMP算法完整教程 全称: Knuth_Morris_Pratt Algorithm(KMP算法) 类型: ...
- 【★】KMP算法完整教程
KMP算法完整教程 全称: Knuth_Morris_Pratt Algorithm(KMP算法) 类型: ...
- 第4章学习小结_串(BF&KMP算法)、数组(三元组)
这一章学习之后,我想对串这个部分写一下我的总结体会. 串也有顺序和链式两种存储结构,但大多采用顺序存储结构比较方便.字符串定义可以用字符数组比如:char c[10];也可以用C++中定义一个字符串s ...
- 【数据结构】KMP算法
我还是不太懂... 转2篇大神的解释 1>https://www.cnblogs.com/yjiyjige/p/3263858.html 2>https://blog.csd ...
- [转]KMP算法
KMP算法应该是每一本<数据结构>书都会讲的,算是知名度最高的算法之一了,但很可惜,我大二那年压根就没看懂过~~~ 之后也在很多地方也都经常看到讲解KMP算法的文章,看久了好像也知道是怎么 ...
随机推荐
- 四则运算GUI
一.题目描述 我们在个人作业1中,用各种语言实现了一个命令行的四则运算小程序.进一步,本次要求把这个程序做成GUI(可以是Windows PC 上的,也可以是Mac.Linux,web,手机上的),成 ...
- 事后诸葛亮分析(Beta版本)
全组讨论的照片 设想和目标 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 解决代码分析.统计.管理等问题,定义的很清楚,有清晰的描述. 是否有充足的时间来做计划? ...
- 团队作业6--展示博客(Alpha版本)
1.团队成员简介和个人博客地址 团队源码仓库地址:https://git.coding.net/tuoxie/dianziwendangchachong.git吕志哲 201421123021 个人博 ...
- 201521123074 《Java程序设计》第3周学习总结
1.本周学习总结 用百度脑图画了一张,点开图片全屏就可以看清楚了 脑图链接 2.书面作业 Q1.代码阅读 以下代码可否编译通过?哪里会出错?为什么?尝试改正? 如果创建3个Test1对象,有内存中有几 ...
- 201521123069 《Java程序设计》第1周学习总结
1. 本章学习总结 Java语言的发展.特点(面向对象.简单性.平台无关性) 认识并区分JVM(Java虚拟机),JRE(Java执行环境),JDK(Java开发工具包) 安装好JDK,设置Path变 ...
- Python中库或者模组的解释
- 201521123106 《Java程序设计》第11周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 2. 书面作业 本次PTA作业题集多线程 互斥访问与同步访问 完成题集4-4(互斥访问)与4-5(同步访问) 1. ...
- 201521123092《java程序设计》第九周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 2. 书面作业 本次PTA作业题集异常 1.常用异常 题目5-1 1.1 截图你的提交结果(出现学号) 1.2 自己 ...
- c#中的格式输出
Reference:http://blog.csdn.net/fightfaith/article/details/48137235
- 框架应用:Spring framework (四) - 事务管理
事务控制 事务是什么?事务控制? 事务这个词最早是在数据库中进行应用,讲的用户定义的一个数据库操作序列,这些操作要么全做要么全不做,是一个不可分割的工作单位. 事务的管理是指一个事务的开启,内容添加, ...