KMP算法——快速从字符串M(母串)中找出与字符串Z(子串)匹配的子串

例1:

0 1 2 3 4 5

M:a b c a b d

Z:  a b d

BF算法(最一般的算法,也叫“蛮力算法”):

将Z[0]-M[0](用“-”表示比较),如果=,则Z[1]-M[1],...直到Z[i]!=M[i],回溯

然后Z[0]-M[1],同上方法~最常见的做法,很容易理解,可是效率比较低。

KMP算法:比较过的字符段也是有信息可以利用的。

如例1,Z匹配M到   Z[2]=d  !=  M[2]=c, 说明什么?说明前面Z[0]=M[0],Z[1]=M[1],一一对应相等。

然后需要回溯让Z[0]去和M[1]比较吗?其实没有必要

为什么? 看Z  =ab d    d前每个字符各不相同,既然 M=ab cxxxxxx(因为Z与M比较到d,对应的M前面的和Z一一对应相等,可以推测到M失配字符前面的字符),

BF算法是发现不匹配后让Z[0]=a回去和M[i](i=1,2,3...依次递增)比较,只有M[i]=Z[0],才有资格比较M[i+1]和Z[1],继续下一位比较下去,否则判断不等后直接就换下一位了,毫无意义。

但是我们研究了Z后发现  :   Z中d前面的字符(ab)串除了Z[0](a)外没有和Z[0]相同的了,那么由于M失配字符之前的字符都是和Z对应相同的,所以推测M失配之前的字符肯定没有与Z[0]相等的,所以他们都没有必要和M[0]去比较 直接可以拿Z[0]从失配点向后比较就可以了。

好吧,我们发现Z上面还是有点信息的(重点理解红字的意思),但还是有点模糊

例2:    0 1 2 3 4 5

M:a b c a b d e a f a f

Z:  a b c a b e

看例2.明显Z[5]与M[5]失配。只需要看Z就能推测出M[0]~M[4]是什么。而我们失配之后,下一次匹配比较的前提就是M[i]=Z[0](i=1,2,3....),所以看Z匹配部分

a b c a b  ,推测出M对应的M[3]M[4]=ab,下次可以从M[3]开始匹配,有成功可能性。但是如果换成 如下

0 1 2 3 4 5

M:a b c a d d e a f a f

Z:  a b c a d e

Z=a b c a d 虽然Z[3]=Z[0],但明显Z[4]!=Z[1],依然无法匹配,所以我们发现只有Z失配字符前呈现abxxab类型,才可从M对应ab处开始下一次监测匹配,否则M失配前的字符均无法匹配Z(如例1所示),所以也无需进行判断。

所以下一步我们只要知道Z匹配比较到第n位,那么我们通过分析Z的前n-1的字符串,分析它们的对称性,就可以判断出对应M下次开始比较的位置。

数据结构语言只是工具,关键是解决问题的思想。

这就是基本思想,具体代码网上随处可见,就不继续写了,表达可能还是不太清楚,多看两遍理解了思想,就豁然开朗了。

后面补充一种其他算法思想:

RK算法:

一个字符一个字符的比较会不会有点慢呢?

如果把n个字符的Z当成一个数z,把M的n个连续字符子串也当成一个数m。

那么如果z!=m,则M对应的该子串肯定和Z不同;反之,z=m就有很大可能相同了,只需要在一个较小的范围内逐个字符比较就好,反正又不多。

M:a b c a b d e a f a f     m=abcabd

Z:  a b c a b e                  z=abcabe

不等?m=bcabde(向后移动一位),继续比较,直到m=z,然后比较Z和M子串。其实挺快的这个方法~具体代码网上找

一眼看懂KMP匹配算法的更多相关文章

  1. 搞定KMP匹配算法

    KMP算法介绍及实现——轻松搞定KMP匹配算法 本文介绍了字符串匹配算法中的BF算法和KMP算法.本文中KMP算法介绍部分是关于KMP算法相关文章中最简洁的一篇文章之一.下一篇将继续介绍Horspoo ...

  2. 4-4-串的KMP匹配算法-串-第4章-《数据结构》课本源码-严蔚敏吴伟民版

    课本源码部分 第4章  串 - KMP匹配算法 ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接☛☛☛ <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码 ...

  3. 数据结构——串的朴素模式和KMP匹配算法

    一.朴素模式 假设我们要从主串S="goodgoogle"中找到子串T="google"的位置,步骤如下: i表示主串的当前位置下标,j表示子串的当前位置下标, ...

  4. c语言KMP匹配算法与字符串替换算法

    一.字符串匹配算法 (1)传统匹配算法BF int Index_BF(char* S, char* T){ int i=1,j=1; while(i<=strlen(S) && ...

  5. KMP匹配算法 - Number Sequence

    Given two sequences of numbers : a[1], a[2], ...... , a[N], and b[1], b[2], ...... , b[M] (1 <= M ...

  6. KMP匹配算法

    先来说一下回溯法匹配字符串: 对于主字符串有一个target_index,以target_index(不动)为起点,匹配字符串pattern的长度+target_index为终点,逐个进行比较,当发现 ...

  7. 一眼看懂深浅拷贝(clone)-C#

    这是使用的是序列化的方式实现深拷贝 [Serializable] class Person:ICloneable { /// <summary> /// 字符串在clone 中类似于值类型 ...

  8. linux tar 命令 --致力于“一眼看懂,随手就用”的随笔

    基本玩法: 压缩: tar -czf txt.tar.gz *.txt // 将当前目录下的所有txt文件,创建一个tar包,并用gzip算法,压缩成txt.tar.gz 文件 解压: tar -xz ...

  9. 一眼看懂promise async的区别

    // promise方法 let p1 = new Promise((resolve,reject) => { setTimeout(() => { resolve('我是p1') },4 ...

随机推荐

  1. Cocos2d-x 核心概念 - 导演(Director)

    导演类(Director) 用于管理场景对象,采用的是单例模式(单例模式能保存一致的配置信息,方便管理场景对象) 获得导演实例的语句如下 local director = cc.Director:ge ...

  2. MVC文章汇总

    http://www.cnblogs.com/yaozhenfa/category/541420.html http://www.cnblogs.com/yubaolee/p/3269043.html ...

  3. 给ListBox每项加图标

    先设置listBoxMsg.DrawMode = DrawMode.OwnerDrawFixed; private void listBoxMsg_DrawItem(object sender, Dr ...

  4. Scope 安装和使用

    Scope 安装和使用 一.安装 1. 软件下载 https://sourceforge.net/projects/cscope/files/ 2. 解压 3. 安装 ./configure --pr ...

  5. linux diff命令

    diff 命令是 linux上非常重要的工具,用于比较文件的内容,特别是比较两个版本不同的文件以找到改动的地方.diff在命令行中打印每一个行的改动.最新版本的diff还支持二进制文件.diff程序的 ...

  6. PHP简单文件上传

    一个简单的PHP上传文件的例子: upload.html <html> <body> <form action="upload.php" method ...

  7. select 和 input 的不可编辑,input隐藏

    select 没有readOnly属性 在jsp中 <select  id="a" name="a" disabled="disabled&qu ...

  8. 转:图解Git[强烈推荐]

    https://my.oschina.net/xdev/blog/114383 再次感谢原著作者和中文翻译者. 此页图解git中的最常用命令.如果你稍微理解git的工作原理,这篇文章能够让你理解的更透 ...

  9. 初识Polymer框架

    什么是polymer? polymer由谷歌的Palm webOS团队打造,并在2013 Google I/O大会上推出,旨在实现Web Components,用最少的代码,解除框架间的限制的UI 框 ...

  10. malloc error:初始值设定元素不是常量

    #include <stdio.h> #include <stdlib.h> char *buf = (char *)malloc(BUFSIZ); setbuf(stdout ...