KMP算法最浅显理解(小白教程)

KMP算法最浅显理解(小白教程)

什么是KMP算法?

KMP算法(Knuth-Morris-Pratt算法)是一种字符串匹配算法,用于在一个主串中查找一个模式串的出现位置。与朴素的字符串匹配算法相比,KMP算法具有更高的效率。

KMP算法的基本思想

KMP算法的基本思想是利用已经匹配过的部分信息,避免不必要的回溯。它通过构建一个部分匹配表(Partial Match Table),来记录模式串中的前缀和后缀的最长公共部分长度,从而在匹配过程中跳过一些不可能匹配的位置。

构建部分匹配表

部分匹配表是KMP算法的核心,它记录了模式串中每个位置的最长公共前缀后缀长度。下面是构建部分匹配表的步骤:

  1. 初始化部分匹配表,长度与模式串相同,初始值都为0。
  2. 从模式串的第二个字符开始,依次计算每个位置的最长公共前缀后缀长度。
  3. 对于每个位置i,假设前缀为P[0:i-1],后缀为P[1:i],计算它们的最长公共部分长度。
  4. 如果P[0:i-1]的最长公共部分长度为k,且P[i-1]等于P[k],则P[0:i]的最长公共部分长度为k+1。
  5. 如果P[0:i-1]的最长公共部分长度为k,且P[i-1]不等于P[k],则需要继续向前寻找更短的公共前缀后缀。
    • 如果P[0:k-1]的最长公共部分长度为m,且P[i-1]等于P[m],则P[0:i]的最长公共部分长度为m+1。
    • 如果P[0:k-1]的最长公共部分长度为m,且P[i-1]不等于P[m],则继续向前寻找更短的公共前缀后缀,直到找到长度为0的公共前缀后缀。
  6. 重复步骤3,直到计算完所有位置的最长公共前缀后缀长度。

KMP算法的匹配过程

KMP算法的匹配过程如下:

  1. 初始化主串的位置i为0,模式串的位置j为0。
  2. 逐个比较主串和模式串的字符:
  3. 如果主串的字符和模式串的字符相等,则继续比较下一个字符。
  4. 如果主串的字符和模式串的字符不相等:
    • 如果j等于0,表示模式串的第一个字符就不匹配,将i加1。
    • 如果j大于0,表示已经匹配了j个字符,但第j+1个字符不匹配,根据部分匹配表,将j更新为部分匹配表中j位置的值,继续比较主串的字符和模式串的字符。
  5. 如果模式串的位置j等于模式串的长度,表示匹配成功,返回主串中匹配的起始位置。
  6. 如果主串的位置i等于主串的长度,表示匹配失败,返回-1。

示例说明

示例1

主串:\"ABABABABCABABABABD\"
模式串:\"ABABABD\"

构建部分匹配表:

位置 字符 部分匹配值
0 A 0
1 B 0
2 A 1
3 B 2
4 A 3
5 B 4
6 D 0

匹配过程:

  • 第一步:i=0, j=0,A和A匹配。
  • 第二步:i=1, j=1,B和B匹配。
  • 第三步:i=2, j=2,A和A匹配。
  • 第四步:i=3, j=3,B和B匹配。
  • 第五步:i=4, j=4,A和A匹配。
  • 第六步:i=5, j=5,B和B匹配。
  • 第七步:i=6, j=6,D和D匹配。
  • 匹配成功,返回主串中匹配的起始位置为3。

示例2

主串:\"ABCABABABD\"
模式串:\"ABABABD\"

构建部分匹配表:

位置 字符 部分匹配值
0 A 0
1 B 0
2 A 1
3 B 2
4 A 3
5 B 4
6 D 0

匹配过程:

  • 第一步:i=0, j=0,A和A匹配。
  • 第二步:i=1, j=1,B和B匹配。
  • 第三步:i=2, j=2,C和A不匹配,根据部分匹配表,j更新为2。
  • 第四步:i=2, j=2,C和A不匹配,根据部分匹配表,j更新为1。
  • 第五步:i=2, j=1,C和B不匹配,根据部分匹配表,j更新为0。
  • 第六步:i=2, j=0,C和A不匹配,将i加1。
  • 第七步:i=3, j=0,A和A匹配。
  • 第八步:i=4, j=1,B和B匹配。
  • 第九步:i=5, j=2,A和A匹配。
  • 第十步:i=6, j=3,B和B匹配。
  • 第十一步:i=7, j=4,A和A匹配。
  • 第十二步:i=8, j=5,B和B匹配。
  • 第十三步:i=9, j=6,A和D不匹配,根据部分匹配表,j更新为0。
  • 第十四步:i=9, j=0,A和A匹配。
  • 第十五步:i=10, j=1,B和B匹配。
  • 第十六步:i=11, j=2,A和A匹配。
  • 第十七步:i=12, j=3,B和B匹配。
  • 第十八步:i=13, j=4,A和A匹配。
  • 第十九步:i=14, j=5,B和B匹配。
  • 第二十步:i=15, j=6,A和D不匹配,根据部分匹配表,j更新为0。
  • 第二十一步:i=15, j=0,A和A匹配。
  • 第二十二步:i=16, j=1,B和B匹配。
  • 第二十三步:i=17, j=2,A和A匹配。
  • 第二十四步:i=18, j=3,B和B匹配。
  • 第二十五步:i=19, j=4,A和A匹配。
  • 第二十六步:i=20, j=5,B和B匹配。
  • 第二十七步:i=21, j=6,A和D不匹配,根据部分匹配表,j更新为0。
  • 匹配失败,返回-1。

以上就是KMP算法的最浅显理解,希望对你有帮助!

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:KMP算法最浅显理解(小白教程) - Python技术站

(0)
上一篇 2023年8月6日
下一篇 2023年8月6日

相关文章

  • vue 组件中slot插口的具体用法

    当然!下面是关于\”Vue组件中slot插槽的具体用法\”的完整攻略,包含两个示例说明。 … … … … 示例1:默认插槽 <template> <div> <h1>父组件</h1> <slot></slot> </div> </template>…

    other 2023年8月20日
    00
  • rundll32.exe应用程序错误的解决方法

    当系统运行rundll32.exe文件时,有可能会出现应用程序错误的情况。可能的原因是rundll32.exe文件本身出现了问题,或是某些相关的库文件出现了损坏。针对这个问题,以下是解决方法的完整攻略: 步骤一:检查系统文件 在开始解决rundll32.exe应用程序错误之前,我们需要检查系统文件的完整性。我们可以使用Windows自带的SFC(System…

    other 2023年6月25日
    00
  • python单向循环链表实例详解

    Python 单向循环链表实例详解 单向循环链表是一种常用的链表结构,它和单向链表的最大区别在于其尾节点指向头节点。这种循环的结构使得我们可以轻松地在链表中进行循环操作。下面我们来详细讲解如何使用 Python 实现单向循环链表。 实现思路 实现节点类:首先我们需要定义一个节点类,用来储存我们链表中的每个节点,并且需要定义一些方法来访问和更新节点的值、指针等…

    other 2023年6月27日
    00
  • C#将时间转成文件名使用方法

    C#中将时间转成文件名可以通过以下方法实现: 使用DateTime.Now.ToString()方法将当前时间转成字符串。 string fileName = DateTime.Now.ToString("yyyyMMddHHmmssfff"); 通过此方式可以将当前时间转成年月日时分秒毫秒的格式,例如20210712133456005,…

    other 2023年6月26日
    00
  • vue中页面跳转的几种方法总结

    在Vue中,页面跳转是一个非常常见的需求。本文将总结几种Vue中页面跳转的方法,包括路由跳转、组件跳转和页面刷新等。 1. 路由跳转 Vue中的路由跳转是通过Vue Router实现的。Vue Router是Vue.js官方的路由管理器,可以实现单页应用的路跳转。以下是一个简单的路由跳转示例: <template> <div> &lt…

    other 2023年5月7日
    00
  • java开发技巧代码写的快且bug少的原因分析

    Java开发技巧:代码写得快且Bug少的原因分析 在Java开发中,写出高效且质量良好的代码是每个开发者的追求。下面是一些可以帮助你提高开发效率、减少Bug的技巧和原则。 1. 遵循面向对象编程原则 面向对象编程原则是Java开发的基石。以下是一些重要的原则: 单一职责原则(SRP):每个类应该只有一个责任。这样可以使类的设计更加清晰,易于理解和维护。 开闭…

    other 2023年7月27日
    00
  • Android实现Service重启的方法

    下面是详细讲解 Android 实现 Service 重启的方法的完整攻略。 什么是 Service 重启? Service 是 Android 中的一种组件,它可以在后台运行长时间的任务,即使应用退出或者被杀掉也能够继续运行。但是有时候,由于各种原因,Service 会被系统或者其他应用杀掉,这时候我们需要实现 Service 重启,让 Service 能…

    other 2023年6月27日
    00
  • latticeplanner规划详解

    LatticePlanner规划详解 LatticePlanner是一个用于自主移动机器人的规划算法。本文将详细介绍该算法的实现过程和优势。 什么是LatticePlanner? LatticePlanner是一种运用基于节点的构建方法在连续动态系统中进行快速优化的规划算法。这种算法可以快速计算出由多个机器人、机器人和障碍物之间的交互动作组成的最优路径,并在…

    其他 2023年3月29日
    00
合作推广
合作推广
分享本页
返回顶部