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算法的文章,看久了好像也知道是怎么 ...
随机推荐
- 转:深入Java集合学习系列:HashMap的实现原理
1. HashMap概述: HashMap是基于哈希表的Map接口的非同步实现(Hashtable跟HashMap很像,唯一的区别是Hashtalbe中的方法是线程安全的,也就是同步的).此实现提供所 ...
- RobotFramework安装完成后怎么在桌面显示ride图标
安装了RobotFramework后,怎么让桌面上显示带有机器人的图标呢? 一.桌面上创建ride快捷方式 进入到python的安装目录的/Scripts目录下,找到ride.py文件-->右键 ...
- About Cheating and Plagiarism
我先描述一下此次事件的具体经过.昨天3月15号的晚上十点,是第四次作业的deadline.在15号之前,只有五位同学提交了作业,而在临近deadline的这几个小时内密密麻麻地提交了二十多份作业.和第 ...
- 团队作业6——展示博客(Alpha版本)
Deadline: 2017-5-7 22:00PM,以博客发表日期为准 评分基准: 按时交 - 有分,检查的项目包括后文的四个方面 团队成员介绍 Alpha阶段进展 团队合作,各成员分工 Beta阶 ...
- 团队作业8——第二次项目冲刺(Beta阶段)第三天
BETA阶段冲刺第三天 1.当天站立式会议 2.每个人的工作 (1)昨天已完成的工作: 编写页面讨论 (2)今天计划完成的工作: 完成编写页面 (3)工作中遇到的困难: 验证码正确度 (4)每个人的贡 ...
- Java学习9——面向对象
(重点:内存分析) 类的定义 //用class关键字定义一个类 class Person { //成员变量定义 private int id; private int age = 20; //方法定义 ...
- 201521123078《Java程序设计》第1周学习总结
1. 本周学习总结 简单的了解JVM,JRE,JDK,编写简单的Java程序 2. 书面作业 为什么java程序可以跨平台运行?执行java程序的步骤是什么?(请用自己的语言书写) 通过JVM虚拟机, ...
- 陈敏-第一周Java课程总结
一.本周学习总结 1.感受到JAVA的神奇魅力,以及其跨平台的优势 2.第一次接触感觉还是有很多不懂. 3.了解了JDK 二.书面作业 (一)为什么java程序可以跨平台运行?执行java程序的步骤是 ...
- 201521123051《Java程序设计》第十三周学习总结
1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 书面作业 1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jmu ...
- 201521123113《Java程序设计》第9周学习总结
1. 本周学习总结 2. 书面作业 本次PTA作业题集异常 Q1.常用异常 题目5-1 1.1 截图你的提交结果(出现学号) 1.2 自己以前编写的代码中经常出现什么异常.需要捕获吗(为什么)?应如何 ...