引子:BF暴力算法

KMP算法知名度相当高,燃鹅其理解难度以及代码实现对于初学数据结构和算法的同学并不友好,经过两天的总结,详细总结KMP算法如下:

初学串的模式匹配时,我们都会接触到,或者说应该能想到作为教学引子的BF暴力算法,那么先来简单了解一哈:

我有一个大串是"abccabca",小串是"bca",现在要找到小串在大串中的位置,战斗开始

这个算法理解起来肥肠简单,我在这里假定 i 指针指向大串(主串)的首地址,指针指向小串(模式串)的首地址。首先大串第一位正面对比小串第一位,两元素若相等,则两指针分别后移,继续比较第二位。那么这个算法被称为暴力算法的原因就在于当两串元素对比不相等时,j指针就会回溯到小串的首地址,这本无可厚非,而i指针却会回溯到对比之初的后一位,比如上述第四步大小串匹配不上之后i指针马上来到了第三位,导致了完全无用的第五和第六步比较,造成了算法时间复杂度的加大,而且主串元素数嵌套小串元素数的两重循环,直接造成了O(m*n)的人间大惨案。虽然能实现模式匹配,但是我们的D.E.Knuth、J.H.Morris和V.R.Pratt觉得这个算法有必要改进一哈(V.R.Pratt:嘤嘤嘤),而且出于科学家的身份和*友情缘,三位同时研究出了一个船(全)新的匹配方式,KMP算法横空出世,当然只要体验三分钟,你就会跟我当时一样,放弃这个算法。

附:BF暴力算法代码(取自《大话数据结构》   ps: S[0]、T[0]表示该串的长度)

第一章:kmp算法

黄历上写明了,这个算法不宜先学代码,否则可能会造成理解困难。我这里还是先以一个例子来讲解一下这三个外国同学的算法:

(例子取自《大话数据结构》)

不难发现,我们的模式串没有一个字母是重复出现的,而第一步已经确诊主串和模式串的前五位一模一样,所以你如果这时候使用BF暴力算法,依次用主串的第二位到第五位跟模式串的首位正面刚,就是人傻劲大,完全莫得必要。所以我们要想个办法避免这种重复浪费的现象,结合上面的BF例子,我们也可以明白,这种现象的出现并非是 j 指针的错,而是 i 指针作为主串的指针瞎回溯造成的匹配浪费。

好的,理解了上面的步骤为啥子是多余的,我们再次征讨一下曾被我们用了很长一段时间的暴力算法,正因为它能力有限,只能通过把 i 回溯到一个很靠前的位置才能实现匹配,重点来了,这时来了一个叫做KMP的人,告诉你BF能做到的他也能做到,甚至能把时间复杂度降为O(m+n),这个时间复杂度是什么概念,意味着 i 再也不用承受眼看着无用还不得不回溯的命运。我们来看看KMP算法是怎样干掉BF这个老黄牛的。(前方高能,佩戴脑子食用效果更佳)

要想 i 值不回溯,就一定要在 j 上面做文章,我们再次看看上面的例子,如果第一步刚发现 i=6 两串不匹配时,摁住 i 指针,让 i 继续=6 ,然后这时候使j指针回到初始的位置,即 i = 6 时 j = 1,让主串中的 f 和模式串的 a 比较,就很完美辽,那这里也可能有机智的同学问,要是我的模式串中出了一个和首元素相等的元素怎么破?(/手动狗头),不妨看看这个例子,主串是 "abcabcabx", 模式串是 "abcabx" ,当然贼符合你的心意,当用BF第一轮比到第六位,发现 c x 不一样,这时你会想,把 i 回溯到第四个元素(即 a),再用 j = 1 直接就出结果。但是你想一想,可否不移动 i ,让 j = 3 直接匹配,况且这个例子只是特殊情况,所以怎样看来都是不必回溯 i 的,下面我们看看怎样让 j 发挥他的作用。

既然是 j 的事,就和主串没关系了,我们来研究一下上一段这个例子,我们刚才为什么要移动 j 让他等于3,为了省去模式串前面存在的重复比较,这个重复比较是哪来的呢,就在于 模式串结构中的前后重复程度, "abcabx"这个例子中的串可以分为 "a"+"bcabx" 、"ab"+"cabx"、"abc"+"abx"、"abca"+"bx"、"abcab"+"x",前缀有"a"、"ab"、"abc"、"abca"、"abcab",定义第一个前缀重复度为0,第二个前缀重复度为1,第三个也是1,第四个我们不难发现首尾呼应,所以他的重复度较前面的加一是2,最后一个前缀ab段重复,故重复度为3。

那我们求出这个重复度有毛用呢,我们再看看那个例子,当我们在第一轮发现第六个不相等时,我们可以发现前五位重复度为3,这个3眼熟不,他可以直接在 i 不回溯的前提下把 j 带到正确的位置,即 j = 3,那我们模式串的每一个数都需要这个值来实现KMP算法,我们用一个 next[x] 数组来储存这些数,至于x的大小取决于你的模式串长度。

这时候我们来看看KMP算法的代码(当然还是来自《大话数据结构》的伪码):

这段代码是获得 next数组 的

敲了芥末多的字,希望大家可以快速理解这个KMP模式匹配算法,未完待续.......

预告第二章:KMP算法的改进版本

届时神秘的nextval数组将浮现江湖

continued

 

(原创)白话KMP算法详解的更多相关文章

  1. KMP算法详解(转自中学生OI写的。。ORZ!)

    KMP算法详解 如果机房马上要关门了,或者你急着要和MM约会,请直接跳到第六个自然段. 我们这里说的KMP不是拿来放电影的(虽然我很喜欢这个软件),而是一种算法.KMP算法是拿来处理字符串匹配的.换句 ...

  2. kmp算法详解

    转自:http://blog.csdn.net/ddupd/article/details/19899263 KMP算法详解 KMP算法简介: KMP算法是一种高效的字符串匹配算法,关于字符串匹配最简 ...

  3. [转] KMP算法详解

    转载自:http://www.matrix67.com/blog/archives/115 KMP算法详解 如果机房马上要关门了,或者你急着要和MM约会,请直接跳到第六个自然段.    我们这里说的K ...

  4. 算法进阶面试题01——KMP算法详解、输出含两次原子串的最短串、判断T1是否包含T2子树、Manacher算法详解、使字符串成为最短回文串

    1.KMP算法详解与应用 子序列:可以连续可以不连续. 子数组/串:要连续 暴力方法:逐个位置比对. KMP:让前面的,指导后面. 概念建设: d的最长前缀与最长后缀的匹配长度为3.(前缀不能到最后一 ...

  5. 数据结构4.3_字符串模式匹配——KMP算法详解

    next数组表示字符串前后缀匹配的最大长度.是KMP算法的精髓所在.可以起到决定模式字符串右移多少长度以达到跳跃式匹配的高效模式. 以下是对next数组的解释: 如何求next数组: 相关链接:按顺序 ...

  6. KMP算法详解&&P3375 【模板】KMP字符串匹配题解

    KMP算法详解: KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt(雾)提出的. 对于字符串匹配问题(such as 问你在abababb中有多少个 ...

  7. KMP算法详解-彻底清楚了(转载+部分原创)

    引言 KMP算法指的是字符串模式匹配算法,问题是:在主串T中找到第一次出现完整子串P时的起始位置.该算法是三位大牛:D.E.Knuth.J.H.Morris和V.R.Pratt同时发现的,以其名字首字 ...

  8. 字符串匹配KMP算法详解

    1. 引言 以前看过很多次KMP算法,一直觉得很有用,但都没有搞明白,一方面是网上很少有比较详细的通俗易懂的讲解,另一方面也怪自己没有沉下心来研究.最近在leetcode上又遇见字符串匹配的题目,以此 ...

  9. <转>KMP算法详解

    看了好久的KMP算法,都一直没有看明白,直到看到了这篇博客http://www.tuicool.com/articles/e2Qbyyf让我瞬间顿悟. 如果你看不懂 KMP 算法,那就看一看这篇文章 ...

随机推荐

  1. 转:Java并发集合

    引自:http://ifeve.com/concurrent-collections-1/ 并发集合(一)引言 声明:本文是< Java 7 Concurrency Cookbook>的第 ...

  2. Spring异常重试框架Spring Retry

    Spring Retry支持集成到Spring或者Spring Boot项目中,而它支持AOP的切面注入写法,所以在引入时必须引入aspectjweaver.jar包. 快速集成的代码样例: @Con ...

  3. 「PHP」观察者模式模式

    引言   所属:行为型模式,常用设计模式之一       学习资料: <大话设计模式>程杰 模式概述   观察者模式定义了一种一对多的依赖关系,让多个观察者对象监听某一个主题对象.这个主题 ...

  4. QK对中断的特殊处理

    1.QK的特性 QK(Quntum Kernel)是一个抢占式.基于优先级实时微内核.一个多任务调度器: QK不同于传统的RTOS,是非阻塞的,并且只用了一个stack: 对QK中的任务来说,采用了I ...

  5. AS5600磁编码器开发记录

    AS5600使用简介--(程序员版) -----------------本文由"智御电子"提供,同时提供范例教程,以便电子爱好者交流学习.---------------- 前言: ...

  6. pyhton新手学习之增删改查

    一 .列表的定义 1.列表的定义     names = [ "xiajiqni", "test", "wangwu","oldb ...

  7. Python学习笔记四:列表,购物车程序实例

    列表 切片 中括号,逗号分隔,可以一次取出多个元素,起始位置包括,结束位置不包括(顾头不顾尾) 如果取最后一个,而且不知道列表长度,可以使用负数(-1是最后一个,以此类推) 如果取最后几个,记住从左往 ...

  8. Python 爬虫 (四)

    requests: 练手 雪qiu网 import requests import json import re import pymysql url = 'https://xueqiu.com/v4 ...

  9. 说一说MySQL的锁机制

    锁概述 MySQL的锁机制,就是数据库为了保证数据的一致性而设计的面对并发场景的一种规则. 最显著的特点是不同的存储引擎支持不同的锁机制,InnoDB支持行锁和表锁,MyISAM支持表锁. 表锁就是把 ...

  10. Log4net 配置实例

    首先需要下载并引用Log4net的binary.这一步可以通过在Visual Studio里的Manage Nuget package for solution轻松添加. 第二步是配置config文件 ...