理解 KMP 算法
|
KMP(The Knuth-Morris-Pratt Algorithm)算法用于字符串匹配,从字符串中找出给定的子字符串。但它并不是很好理解和掌握。而理解它概念中的部分匹配表,是理解 KMP 算法的关键。 这里的讨论绕开其背后晦涩难懂的逻辑,着重从其运用上来理解它。 字符串查找比如从字符串 朴素的解法,我们可以这样做,
这种朴素解法的弊端在于,每次匹配失败,索引只后移一位,有很多冗余操作,效率不高。 在进行第一轮匹配中,即索引为 0 时,我们能够匹配出前四个字符 部分匹配表/Partial Match Table以长度为 8 的字符串 char: | a | b | a | b | a | b | c | a | 其中 子集对于上面示例字符串,假如我们观察第 前缀 & 后缀对于给定的字符串,从末尾开始去掉一个或多个字符,剩下的部分都叫作该字符串的真前缀(Proper prefix),后面简称前缀。这里「真」不是「真·前缀」的意思,联想一下数学里面集合的「真子集」。比如
同理,从首部开始,去掉一个或多个字条,剩下的部分是该字符串的真后缀(Proper suffix)。还是
部分匹配值可以看到,所有前缀和后缀在数量上是对称的,那么我们可以从前缀中找出一个,与后缀进行匹配,先不关心做这个匹配的意义。以最开始的文本 假如我们观察
将前缀依次在后缀中去匹配,这里前后缀列表中能够匹配上的只有 再比如来观察
此时可观察出其匹配项为 再比如来观察
然后拿前缀中每个元素与后缀中的元素进行匹配,最后找出有两个匹配项,
我们取长的这个 所以现在再来看上面的部分匹配表,一是能理解其值是怎么来的,二是能理解其表示的意义,即,所有前缀与后缀的匹配项中长度最长的那一个的长度。 当我们继续,进行到 再继续就到字符串末尾了,即整个字符串 部分匹配表的使用利用上面的部分匹配值,我们在进行字符串查找时,不必每次失败后只移动一位,而是可以移动多位,去掉一些冗余的匹配。这里有个公式如下:
如果匹配过程中,匹配到了部分值为 下面是本文开始时的那个部分匹配表: char: | a | b | a | b | a | b | c | a | 假设需要从 首次匹配发生在总字符串的第二个字符, bacbababaabcbab 此时匹配的长度为 1,部分匹配表中索引为 1-1=0 的位置对应的部分匹配值为 0,所以我们可以向前移动的距离是 继续直到再次发生匹配,此时匹配到的情况如下: bacbababaabcbab 现在匹配到的长度是 5,部分匹配表中 5-1=4 对应的部分匹配值为 3,所以我们可以向前移动 5-3=2,此时一下子就可以移动两位了。 上一次的位置 此时匹配到的长度为 3, 查找到 bacbababaabcbab 此时我们需要查找的字符串其长度已经超出剩余可用来匹配的字符串了,所以可直接结束匹配,得到结论:没有查找到结果。 JavaScript 中的实现以下是来自 trekhleb/javascript-algorithms 中 JavaScript 版本的 KMP 算法实现: /** 时间复杂度因为算法中涉及两部分字符串的线性对比,其时间复杂度为两字符串长度之和,假设需要搜索的关键词长度为 k,总字符串长度为 m,则时间复杂度为 O(k+m)。 相关资源 |
理解 KMP 算法的更多相关文章
- 深入理解KMP算法
前言:本人最近在看<大话数据结构>字符串模式匹配算法的内容,但是看得很迷糊,这本书中这块的内容感觉基本是严蔚敏<数据结构>的一个翻版,此书中给出的代码实现确实非常精炼,但是个人 ...
- KMP算法详解 --- 彻头彻尾理解KMP算法
前言 之前对kmp算法虽然了解它的原理,即求出P0···Pi的最大相同前后缀长度k. 但是问题在于如何求出这个最大前后缀长度呢? 我觉得网上很多帖子都说的不是很清楚,总感觉没有把那层纸戳破, 后来翻看 ...
- 从头到尾测地理解KMP算法【转】
本文转载自:http://blog.csdn.net/v_july_v/article/details/7041827 1. 引言 本KMP原文最初写于2年多前的2011年12月,因当时初次接触KMP ...
- 深入理解KMP算法之续篇
前言: 纠结于KMP已经两天了,相较于本人之前博客中提到的几篇博文,本人感觉这篇文章更清楚地说明了KMP算法的来龙去脉. http://www.cnblogs.com/goagent/archive/ ...
- 真正理解KMP算法
作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4403560.html 所谓KMP算法,就是判断一个模式串是否是一个字符串的子串,通常的算法当 ...
- 理解KMP算法
母串:S[i] 模式串:T[i] 标记数组:Next[i](Next[i]表示T[0~i]最长前缀/后缀数) 先来讲一下最长前缀/后缀的概念 例如有字符串T[6]=abcabd接下来讨论的全部是真前缀 ...
- KMP算法 --- 深入理解next数组
在KMP算法中有个数组,叫做前缀数组,也有的叫next数组. 每一个子串有一个固定的next数组,它记录着字符串匹配过程中失配情况下可以向前多跳几个字符. 当然它描述的也是子串的对称程度,程度越高,值 ...
- 从有限状态机的角度去理解Knuth-Morris-Pratt Algorithm(又叫KMP算法)
转载请加上:http://www.cnblogs.com/courtier/p/4273193.html 在开始讲这个文章前的唠叨话: 1:首先,在阅读此篇文章之前,你至少要了解过,什么是有限状态机, ...
- KMP算法的一次理解
1. 引言 在一个大的字符串中对一个小的子串进行定位称为字符串的模式匹配,这应该算是字符串中最重要的一个操作之一了.KMP本身不复杂,但网上绝大部分的文章把它讲混乱了.下面,咱们从暴力匹配算法讲起,随 ...
随机推荐
- 原生Feign使用详解
一,简介 Feign使得 Java HTTP 客户端编写更方便.Feign 灵感来源于Retrofit.JAXRS-2.0和WebSocket.Feign最初是为了降低统一绑定Denominator到 ...
- Centos7下安装MySql
1.安装MariaDB 安装命令 yum -y install mariadb mariadb-server 安装完成MariaDB,首先启动MariaDB systemctl start maria ...
- Python_Excel文件操作
''' 使用xlrd模块写入Excel文件 ''' import xlrd book=xlrd.open_workbook(r'/Users/c2apple/Desktop/纪录/测试报告/张涛文件盘 ...
- 第七章之S5PV210移植到Nandflash
1,之前的操作都是基于SD卡进行运行的,如今在Nandfalsh中运行u-boot.因为s5p_goni.h配置文件没有配置Nand相关文件,所以先配置Nand文件. 在include/configs ...
- 一种轻量级的微信小程序日志监控的方法
今天一个活动要写个H5,明天一个功能要用小程序,天天都在写bug.用户反馈小程序用起来有问题还特么还不知道到底出了啥bug,反馈多了,老板要扣工资了!看来挖了太多坑不填也不行,程序异常还是要主动追踪, ...
- 【转】Sentry介绍
Sentry 是一个开源的实时错误报告工具,支持 web 前后端.移动应用以及游戏,支持 Python.OC.Java.Go.Node.Django.RoR 等主流编程语言和框架 ,还提供了 GitH ...
- Unity3D学习(六):《Unity Shader入门精要》——Unity的基础光照
前言 光学中,我们是用辐射度来量化光. 光照按照不同的散射方向分为:漫反射(diffuse)和高光反射(specular).高光反射描述物体是如何反射光线的,漫反射则表示有多少光线会被折射.吸收和散射 ...
- vim折叠快捷键
参考:http://www.cnblogs.com/fakis/archive/2011/04/14/2016213.html 1. 折叠方式 可用选项来设定折叠方式: 可在Vim 配置文件中设置 s ...
- linux的远程唤醒
这里主要是针对ubuntu系统的说明 1.检查计算机硬件是否支持WOL(wake on lan)功能. 1.1.检查主板和电源是否支持WOL: 进入BIOS的Power Management Setu ...
- 记录几个经典的字符串hash算法
记录几个经典的字符串hash算法,方便以后查看: 推荐一篇文章: http://www.partow.net/programming/hashfunctions/# (1)暴雪字符串hash #inc ...