导言:本文有如下特色:算法

(1)主要讨论的是严蔚敏老师的《数据结构》中第四章所提到的KMP算法,即带NEXT[]辅助数组的KMP算法;数组

(2)主要针对初学者,对算法不熟悉的同窗,主要目的是但愿经过本文能让初学者快速理解KMP算法的NEXT的计算规则。数据结构

最近复习到KMP算法,发现以前虽然好不容易弄会了手动KMP计算NEXT并且自觉得“理解”了KMP算法,结果复习起来发现基本要重看。痛定思痛,决定完全弄懂这个玩意儿。spa

相信即便是初学者也能理解KMP算法的最大优点在于不须要将模式串回退匹配来提升速度。若是给出了NEXT数组,我估计绝大部分人都可以手动模拟搜索过程。递归

但问题就在于,怎么计算next数组呢?数学

严老师的书上给出了一种对next的计算算法。算法当然是很简单的,重点在于解释的过程。基础

咱们先回顾一下书上的作法。搜索

书上从一种匹配状况出发。im

这种匹配状况中,已知在一次匹配的过程当中有(每一个字符写做p[])next

‘p[1]p[2]..p[k]’=‘..p[j]’(即某段字符相等匹配),而且已知p[j]的next[p[j]]的值为p[k]。

而后再考虑p(k+1)和p(j+1)的匹配状况。

书上的讲解虽然易懂,可是将其直接推演到求解一个模式串的next值得状况时则有些让人摸不着头脑:一个串和本身相比,又是错位相比,仍是在知道某段值得状况下"向前看"去求下一个字符的next[],这是在是很差想象。

即便拿一个具体的例子来看,好比abbab。想要模拟一下这种假设,都让人手忙脚乱。

固然,若是算法基础比较好的同窗也许分分钟搞定了这个问题,可是对于我这种来讲...就须要另外一个想法了!

那么来看看个人办法。

首先,让咱们厘清KMP算法中next[]的意义吧。

next数组中的某个值next[k]的意义在于指出匹配失败时下一次匹配的模式串字符的位置.

它其实是,当模式串中的p[k]与文本串(目标串)t[j]对比时,若是不能匹配,在将模式串右移的过程当中,第一个遇到"合理的"的再一次与t[y]比较的模式串上的字符的位置,即p[next[k]]。

这个地方的合理性在于,从p[next[k]]以前的全部模式串字符,与当前位置下的目标串前面的一部分是彻底相同的,即

'p[1]p[2]...p[next[k]-1]'  =  '...t[j-1]'  =  '...p[k-1]'

厘清合理性后,让咱们来看看怎么求next[]。

对于一个模式串p[],咱们很容易经过定义对其头两个字符的next进行赋值(*:若是第一个字符都不匹配,那么只能讲模式串右移;若是第二个字符不能匹配,那么只能再与第一个字符比较),在此处仍是写做p[1]=0,p[2]=1;。

如今,假设咱们已经对p[k]及其以前的每一个字符都求得了next[]的值(这种假设是合理的,由于咱们显然已经求得了p[1]、p[2]的next[]),那么咱们如今来考虑p[k+1]对应的next值,即next[k+1]=x。

回顾定义,x应当是这样一个值:它能使得,当模式串与目标串已经匹配了k个字符时,即

'p[1]p[2]...p[k-1]p[k]'='...t[j-1]t[j]'

若是p[k+1]!=t[j+1],那么p[x]就是下一个与t[j+1]比较的字符。

根据前面提到的合理性,此时,即移动后的模式串,在p[x]前的那些字符,是与目标串上相应位置上的字符相匹配的,即有:

'p[1]p[2]...p[x-1]'  =  '...t[j-1]'  =  '...p[k]'

注意,此时也就是有

'p[1]p[2]...p[x-1]'='...p[k]'。

此时相等意义正是理解算法的关键。

由于已经说过此时求得了p[k]的next[k]=y为已知,而这个y的意义由前面的合理性知道,有

'p[1]p[2]..p[y-1]'='...p[k-1]'

若是此时再知足:p[y]=p[k],那么此时有:

'p[1]p[2]..p[y-1]p[y]'  =  '...p[k-1]p[k]'  =  'p[1]p[2]...p[x-1]'

也就是说此时知足了以下条件y=x-1!(由KMP的“最长部分匹配”条件能够得此时的推导是充要的,本文重在理解,此处的推理也就不证实啦)。那么咱们就求得了

next[k+1]=x=y+1=next[k]+1

这就是严老师教材所给出的公式,不过严老师教材中的推理比如从后向前看,这里更多的是从前向后看。

不过这个过程还没结束,若是p[y]!=p[k]怎么办?,注意,此时咱们有

'p[1]p[2]..p[y-1]'='...p[k-1]'

因此p[y]的next值即next[y]一样知足前面说到的合理性,所以能够有y2=next[y],继续递归...直到,最后一个yn=1。

整个过程就比如一个解方程的过程,有方程特征(即next[]的性质和KMP的性质),有初值和边界条件(即p[k]及以前的字符的next[]值已知,且当第一个字符不匹配时模式串右移),那么就能够求得P[K+1]的next[]值。

这个理解就写到这里啦,有许多地方数学的表达不严谨,重在理解嘛。

若有勘误,请指正。欢迎讨论!

谢谢阅读!



kmp算法严蔚敏C语言,【菜鸟福音】KMP算法简单理解(从严蔚敏老师的《数据结构》出发)...相关推荐

  1. c语言排序算法实际案例,[C语言] 部分经典排序算法详解(有图解)

    目录 1.内容概括 2.主要算法 3.技术的具体应用 4.算法实际应用 5.总结 0.前言 在上一篇文章<[C语言] 数组的实际应用三则>中我们提到了数组的一些基础知识,并通过三个实际例子 ...

  2. 小红书算法sign php,易语言小红书sign算法源码

    易语言小红书sign算法源码 @397951321.版本 2 .子程序 计算sign, 文本型 .参数 请求参数, HashMap类 .局部变量 A, 文本型, , "0" .局部 ...

  3. c语言算法有效性,BerForest—C语言学习笔记-《算法》

    这是我学习C语言的笔记,也可以算是回忆录,反正有利于我的学习,也可以让C语言的新手借鉴. 许多人都在盲目的学习编程,其实学习编程无为就是学习一些编程语法.即使学会了,也不一定能够自己独立的编写出程序了 ...

  4. bresenham算法画圆c语言,bresenham画圆算法

    中点画圆算法在一个方向上取单位间隔,在另一个方向的取值由两种可能取值的中点离圆的远近而定.实际处理中,用决策变量的符号来确定象素点的选择,因此算法效率较高. 设要显示圆的圆心在原点(0,0),半径为R ...

  5. c语言龙贝格积分法实验报告,数值作业:龙贝格算法计算积分C语言实现

    数值作业:龙贝格算法计算积分C语言实现 数值作业:龙贝格算法计算积分C语言实现 根据Romberg算法计算定积分,和变步长的Simpson算法的输入都一样.算法基本分析:输入a,b(积分上下限),n为 ...

  6. 数据分享|R语言关联规则挖掘apriori算法挖掘评估汽车性能数据

    全文链接:http://tecdat.cn/?p=32092 我们一般把一件事情发生,对另一件事情也会产生影响的关系叫做关联.而关联分析就是在大量数据中发现项集之间有趣的关联和相关联系(形如" ...

  7. 用C语言或C++编写一个简单的银行家算法模拟程序

    1.问题描述 银行家算法是操作系统中避免死锁的典型算法.用C语言或C++编写一个简单的银行家算法模拟程序,实现多个进程争用系统临界资源时的分配过程.要求程序实现: 1.当一进程请求一组资源时,先确定是 ...

  8. 数据结构_dfs深度优先算法入门(C语言)

    数据结构_dfs深度优先算法入门(C语言) 文章目录 数据结构_dfs深度优先算法入门(C语言) 0.闲话 1.个人理解 2.全排列问题(1到n的排列组合) 2.八皇后问题求解 3.二维迷宫 (1)只 ...

  9. 数据拟合算法c语言实现,数据拟合算法剖析及C语言实现.doc

    数据拟合算法剖析及C语言实现 数据拟合算法剖析及C语言实现 [摘要]数据拟合在很多地方都有应用,主要用来处理实验或观测的原始离散数据.通过拟合可以更好的分析和解释数据.在引用前人的算法基础上,采用正交 ...

  10. 计算机导论算法设计,计算机导论精品PPT-第五章 算法与程序设计.ppt

    <计算机导论精品PPT-第五章 算法与程序设计.ppt>由会员分享,可在线阅读,更多相关<计算机导论精品PPT-第五章 算法与程序设计.ppt(52页珍藏版)>请在人人文库网上 ...

最新文章

  1. 使用 C#/.NET Core 实现单体设计模式
  2. 数据库视频总结三(游标和事务)
  3. ECCV 2018论文解读 | DeepVS:基于深度学习的视频显著性方法
  4. 2020年Java讲课笔记目录
  5. 业务监控系统如何做,一起来看看如何使用Statsd+Graphite+Grafana搭建业务监控系统
  6. webview java调用js_android WebView java与js相互调用
  7. 验证手机号码的JS方法
  8. Entering emergency mode . Exit the shell to continue . Type journa lctl to view system logs .
  9. EXCHANGE 2016证书续期
  10. 小小的我,有大大的梦想
  11. Unity 脚本中的几种等待方法
  12. Ubuntu18.04 有线网络显示已连接但无法打开网页
  13. 10年创业消亡史:风口起落的背后,是6271家创业公司的黯然离场
  14. 数据流标准差计算方法-不用事先计算均值
  15. 单片机与ARM嵌入式,DSP,FPGA的联系与区别
  16. bugku---game1
  17. Error in nextTick: TypeError: Cannot read property 'children' of undefined 解决
  18. 非常棒的开源协同办公OA项目,收藏了!
  19. 用js给自己照相并修图
  20. Hive的安装与配置

热门文章

  1. Unity3D中unitypackage文件的图标显示及打开方式异常问题的解决方法(值得收藏)
  2. K.function的用法
  3. 线段树,方差,数学(Variance,玲珑杯 Round#5 H lonlife 1063)
  4. 解决office 2019打开word、excel慢的问题
  5. 2022IEOC全国赛专业组获奖及晋级成绩公布 全球赛期待继续辉煌
  6. jzoj6366. 【NOIP2019模拟2019.9.25】化学(chem)
  7. Arcgis 创建切片包(*.tpk)
  8. python中inf_认识python中的inf和nan
  9. 通过分析周榜前100名专家的博客文章 手把手教你写出爆款文章
  10. (半翻译)篡改mac应用后,如何resign签名,重新获得mac系统的信任?