1.简介

Knuth-Morris-Pratt 算法,简称 \text{KMP}KMP 算法,由 \text{Donald Knuth}Donald Knuth、\text{James H. Morris}James H. Morris 和 \text{Vaughan Pratt}Vaughan Pratt 三人于 19771977 年联合发表。其经常被用于求解字符串匹配算法。

对于暴力匹配算法,让模式字符串 needle 与待匹配主串 haystack 的所有长度为 mm 的子串均匹配一次。如此造成的开销是巨大的,其时间复杂度为O(m*n),空间复杂度为O(1)。

当模式串和待匹配串发生失配时,在暴力匹配算法中,其下一步是完全回退模式串再重新匹配。这样做的好处是简单易于理解,但是却也完全放弃了已匹配的字符中的可用信息

KMP算法的核心在于next数组,next中保存了当前位置匹配失配后,其下一步应该回退多少步,有效的利用了已有的信息。其时间复杂度为O(n+m),空间复杂度为O(m)。

2.代码

即使看起来不太好理解求next的原理,但是其代码却十分的简洁,就几行代码。

int GetNext(char ch[], int length, int next[]){next[1] = 0;int i = 1, j = 0;while(i <= length){if(j==0 || ch[i] == ch[j]){next[++i] = ++j;}else{j = next[j];}}
}

2.1原理

2.2.1前缀后缀

对于失配时回退多少的问题,就要理解前缀和后缀的概念。假如当前匹配到箭头所指的位置,发现A和B并不相等,那么暴力法需要将箭头重新移动到模式串首(黄色串)A。

而实际上我们发现箭头前面的字符串串头和串尾(两个白色框)是相同的,因此实际上我们将箭头移动至相同的字符串串头的白色框就可以继续匹配下去,这两个框就叫做前缀和后缀

在该视频中有对该算法的详细讲解「天勤公开课」KMP算法易懂版_哔哩哔哩_bilibili

2.2.2求next的代码解释

next数组就是记录当前最长公共子串(即最长前缀)的长度加一的大小。

next[1]=0;

首先是模式串的第一个字符,由于其前面没有字符,前缀为0,但是我们习惯上将第一位的前缀记为-1,在加上一之后得到next[1]=0。后续的前缀为0, 当作0 + 1, 也就是说0 只出现在串首。

int i = 1, j = 0;

i 指向当前位置的模式串失配的前一个位置。j 指的是上一个位置的最长前缀 + 1。

if(j==0 || ch[i] == ch[j]){next[++i] = ++j;
}else{j = next[j];
}

该代码是求next数组的核心,其判断条件 j == 0 即模式串上一个位置的前缀为-1(串首),ch[i] == ch[j] 即模式串当前位置与模式串上一位置的前缀后一位匹配,如图:

此时,i 指向当前位置的模式串失配的前一个位置,即 c 发生失配,i 指向b。j 指的是上一个位置的最长前缀 + 1,即abaa的前缀为1,j 指向2。因此 c 对应位置字串abaab的前缀就应该是前一个的基础上加一。

故next[++i] == ++j。

上述为当前位置的字符匹配上的情况,那么如果当前位置未匹配上会发生什么呢。此时b和a失配。

但是j中保存着 前四个字符组成的前缀长度。假设为长度为1。

由红色前缀后缀相同,蓝色前缀后缀相同,推论出红色的后缀部分也应该有蓝色的结构,即

因此当字符失配时,令j = next[j],就得到一个更小的前缀(蓝色),然后比较ch[j] == ch[i],实际上是再比较

如果i 和 j 匹配上了next[++i] = ++j; 如果未匹配上继续向前寻找更小的前缀,直到找到串首即 j == 0。

关于next数组求解的视频KMP算法之求next数组代码讲解_哔哩哔哩_bilibili

2.2总结

简而言之,求next数组分两种情况:

当前 i 指向的字符前一位置的前缀的后一个字符匹配成功,当前位置的最大前缀等于上一位置最大前缀 + 1,i 和 j 分别向后移一位。

当前 i 指向的字符前一位置的前缀的后一个字符匹配不成功,向前寻找到一个更小的前缀,由于前后缀相同,所以更小的前缀保存在next[j]中。

KMP算法求next数组相关推荐

  1. KMP算法求回溯数组的步骤

    KMP算法到底是什么原理就不说了,各种资料上讲的明明白白,下面我就如何用代码来实现做一下说明和记录. KMP的核心思想就是,主串不回溯,只模式串回溯.而模式串匹配到第几位时失配,要回溯多少,由模式串本 ...

  2. KMP算法求Next数组的个人理解(类同qq炫舞)

    最近学了韩顺平老师发布在b站上的数据结构与算法课,发现kmp算法中,求取Next数组的方法有点难理解,下面说一说我自己的感悟. 我感觉求这个数组和玩qq炫舞是一样的,是要达成一种comboo,连续达成 ...

  3. KMP算法的next数组通俗解释

    我们在一个母字符串中查找一个子字符串有很多方法.KMP是一种最常见的改进算法,它可以在匹配过程中失配的情况下,有效地多往后面跳几个字符,加快匹配速度. 当然我们可以看到这个算法针对的是子串有对称属性, ...

  4. KMP算法及next数组(最大公共前后缀)求解

    KMP算法及next数组(最大公共前后缀)求解 2020.12.14理解: 1. KMP算法 网上关于KMP算法讲解较为简单易懂,因此在此只作简述: 在字符串s中匹配字符串t: S: ABE-AB-A ...

  5. KMP算法之next数组详解

    KMP算法之next数组详解 KMP算法实现原理 KMP算法是一种非常高效的字符串匹配算法,下面我们来讲解一下KMP算如何高效的实现字符串匹配.我们假设如下主串和模式串: int i;//i表示主串的 ...

  6. 看了这个你基本就会算kmp算法的next数组了

    看了这个你基本就会算kmp算法的next数组了 kmp算法的next数组求解在计算机专业考研中,以及在大学的数据结构考试中等场合可能会遇到,而遇到后,可能很多同学绕绕脑袋,抓抓头发,却发现还是做不来. ...

  7. KMP算法 → 计算next数组

    [KMP算法简介] KMP算法中的next数组仅取决于模式串本身,而与相匹配的主串无关. KMP算法中的next数组,是KMP算法的核心. KMP算法是由克努特(Knuth).莫里斯(Morris)和 ...

  8. 字符串匹配KMP算法中Next[]数组和Nextval[]数组求法

    数据结构课本上给了这么一段算法求nextval9[]数组 1 int get_nextval(SString T,int &nextval[ ]) 2 { 3 //求模式串T的next函数修正 ...

  9. KMP算法之NEXT数组代码原理分析 - 数据结构和算法38

    KMP算法之NEXT数组代码原理分析 让编程改变世界 Change the world by program KMP算法之NEXT数组代码原理分析 NEXT数组:当模式匹配串T失配的时候,NEXT数组 ...

最新文章

  1. 编写更好的 Java 单元测试的 7 个技巧
  2. CCS(Code Composer Studio) 10.2.0的下载和安装(最新教程)
  3. Camera360与全球1.8亿用户共同创造更美的照片
  4. jQuery之滚动事件$(window).scroll(function()
  5. 【Python】单线程异步多线程多进程实例
  6. Linux学习之路01
  7. ggforce|绘制区域轮廓-区域放大-寻找你的“onepiece”
  8. 扩号匹配问题(信息学奥赛一本通-T1203)
  9. 《中国人工智能学会通讯》——11.64 基于成对约束的属性特征选择
  10. linux 查看运行平台,linux查看程序运行相关命令
  11. 抽象类、接口、内部类
  12. java 自定义函数_Java自定义函数调用方法解析
  13. Mac下实现Word文档批量转换为PDF
  14. Python 实现 批量 复制指定PDF文件 到指定文件夹并批量打印出来
  15. 语音识别 卷积神经网络,卷积神经网络字符识别
  16. VMware虚机丢失vmdk文件恢复方案解析
  17. 经典JavaScript正则表达式实战(转)
  18. 错误:There was a problem confirming the ssl certificate: [SSL: CERTIFICATE_VERIFY_FAILED] certificate
  19. Introduction to CMake by Example
  20. python中 math.isfinite返回值为false_带有Python示例的math.isfinite()方法

热门文章

  1. 如何创建海外美区Apple ID,并使用支付宝购买Apple Store礼品卡,十分钟学会
  2. PPT素材不够用,这5个网站帮你解决
  3. 《隐私政策》及《用户服务协议》
  4. 软件测试之第一章 软件测试和测试环境
  5. javascript 动态设置样式style
  6. 第五届蓝桥杯 软件类省赛真题 第八题:兰顿蚂蚁
  7. Java自学书籍推荐,java程序员面试算法宝典
  8. 2020美团笔试题目:送餐小区数量
  9. c语言求最大公约数多一个负号,C语言 求最大公约数
  10. matlab多个最大公约数,求任意多数的最大公约数及最小公倍数的matlab实现