KMP算法中next[i]与Zi(S)的对应关系

我在《KMP算法详解》一文中已经介绍了next[i]的含义,对于S[i],next[i]的意义是,如果存在k使得S[1...i-k]=S[k...i-1]且S[i-k+1]!=S[i],那么next[i]=i-k+1。实际上对于满足条件的k,其Z值Zk(S)就满足k+Zk(S)=i,next[i]=Zk(S)+1,所以我们可以用如下方法根据模式串S的Zi(S)表填写对应的next[i]表。

规则一,从头到尾遍历Zi(S),当遍历到元素k时,如果Zk(S)!=0,那么next[k+Zk(S)]=Zk(S)+1,如果还存在k'使得k+Zk(S)=k'+Zk'(S)那么next[k+Zk(S)]等于Zk(S)+1与Zk'(S)+1的较大者。

规则二,对于遍历Zi(S)列表之后,尚未填写的元素的next值,我们按照如下原则填充,对于元素S[i],如果S[i]=S[1],则其next值next[i]=0,否则next[i]=1。

根据上面的原则,我们对于《KMP算法详解》中的老例子通过Zi(S)构建next[i]的表格如下。这里对于S[8],由于4+Z4(S)=8,7+Z7(S)=8,所以我们选择其中的较大者Z4(S)=4,令next[8]=Z4(S)+1=5。对于S[9],由于9+Z9(S)超出了pattern数组的范围,所以我们不使用该Z值计算next跳转表。实际对于下表,除了next[8]之外,其余均是由规则二填写。相较于KMP三人给出的next表填写算法,利用Z值表填写next表固然增加了一个转换层,降低了算法效率,但是从易理解的角度讲,由Z值到next值的转换是十分有意义的。

   1  2  3  4  5  6  7  8  9 10
pattern a b c a b c a c a b
Zi(S) 0 0 0 4 0 0 1 0 2 0
next 0 1 1 0 1 1 0 5 0 1

BM算法goodsuffix[i]与Zi(S)的对应关系

用Z值表填写goodsuffix表的过程,要比填写next表复杂得多。首先,BM算法使用的是后缀自包含而Z值计算的是前缀,另一方面我们还需要找到最长的与后缀相匹配的前缀的长度,来修正跳转值。这里我们分别来处理这两个问题。

对于BM算法中的模式串S,我们可以计算其逆串Sr的Z值,Zi(Sr)。例如,对于S="abcxxxabc",Sr="cbaxxxcba",我们可以得到Sr的Z值表如下图所示

   1  2  3  4  5  6  7  8  9
Sr c b a x x x c b a
Zi(Sr) 0 0 0 0 0 0 3 0 0

我们可以用如下方法计算出模式串S的最大包含后缀表rpr(i)。遍历Sr的所有Z值,对于满足n-i-Zi(Sr)+1>0的i,令rpr(n-i-Zi(Sr)+1)=Zi(Sr),对遍历之后未被填充rpr(i)值的元素,赋值0(如果S从索引0开始,则公式要改动为n-i-Zi(Sr))。 如下图,这里要注意,对于i=7,Z7(Sr)=3,但是9-7-3+1<=0,所以我们放弃这个值。

   1  2  3  4  5  6  7  8  9
S a b c x x x a b c
rpr(i) 0 0 0 0 0 0 0 0 0

之后,我们可以计算出未修正的好后缀跳转表。对于rpr(i)=0的元素,goodsuffix'[i]=patlen+n-i,对于rpr(i)!=0的元素,goodsuffix'[i]=n-rpr(i),其中n是模式串最末元素的索引值。如果模式串的首字符从0开始的话,n!=patlen这里要特别注意。

   1  2  3  4  5  6  7  8  9
S a b c x x x a b c
goodsuffix' 17 16 15 14 13 12 11 10 1

另外,我们还需要找到与后缀匹配的最长前缀p,用于修正goodsuffix'的跳转步数。p值在构建Zi(Sr)的时候可以得到,对于Sr中的元素Sr[i],如果有i+Zi(Sr)-1=n,那么p=Zi(Sr),如果有多个i满足该条件,则p等于其中的最大者。上例中对于Sr="cbaxxxcba",我们有7+Z7(Sr)-1=9,所以p=Z7(Sr)=3。在修正goodsuffix'的跳转步数时,我们对于n-i>=p的元素goodsuffix'值统一减去p即可得到最终的goodsuffix值。如下图

   1  2  3  4  5  6  7  8  9
S a b c x x x a b c
goodsuffix 14 13 12 11 10 9 11 10 1

上面虽然列出了4个步骤,但是在实际计算BM的好后缀跳转表的过程中,除了Zi(Sr)需要单独计算之外,其余三个步骤,可以一次完成。

在使用Z值表计算KMP算法或者是BM算法的跳转表的过程中,模式串起始索引要特别注意,如果S[0...n]从0开始,则要对一些地方做修正。因为如果模式串从索引0的位置开始,其最末元素n!=patlen,所以在计算过程中,哪里用的是模式串的长度,哪里用的是模式串最末元素的索引,要格外留心。

再谈KMP/BM算法(II)相关推荐

  1. 【字符串算法1】 再谈字符串Hash(优雅的暴力)

    [字符串算法1] 字符串Hash(优雅的暴力) [字符串算法2]Manacher算法 [字符串算法3]KMP算法 这里将讲述  [字符串算法1] 字符串Hash 老版原文: RK哈希(Rabin_Ka ...

  2. 经典算法研究系列:八、再谈启发式搜索算法

     经典算法研究系列:八.再谈启发式搜索算法 作者:July   二零一一年二月十日 本文参考: I.  维基百科. II. 人工智能-09 启发式搜索. III.本BLOG内,经典算法研究系列:一.A ...

  3. 数据结构与算法--再谈递归与循环(斐波那契数列)

    再谈递归与循环 在某些算法中,可能需要重复计算相同的问题,通常我们可以选择用递归或者循环两种方法.递归是一个函数内部的调用这个函数自身.循环则是通过设置计算的初始值以及终止条件,在一个范围内重复运算. ...

  4. 【徒手写机器学习算法】再谈数据源:从普通图片到Cifar-10(使用C++)

    [徒手写机器学习算法]再谈数据源:从普通图片到Cifar-10(使用C++) 在本系列的第一篇文章里,关于机器学习的数据源的问题被一笔带过(使用csv格式的数据),这一篇文章我会给出关于图片数据制作的 ...

  5. 再谈GC1:GC简介,分代与回收算法

    说明:在本文中, Garbage Collection 翻译为 "垃圾收集", garbage collector 翻译为 "垃圾收集器";一般认为, 垃圾回收 ...

  6. 字符串匹配-BM算法改进SUNDAY--Boyer-Moore-Horspool-Sunday Aglorithm

    原文:http://blog.csdn.net/zhoubl668/article/details/7321271 BM算法的改进的算法SUNDAY--Boyer-Moore-Horspool-Sun ...

  7. 分享一下字符串匹配BM算法学习心得。

    字符串匹配BM(Boyer-Moore)算法学习心得 BM算法 是 Boyer-Moore算法 的缩写,是一种基于后缀比较的模式串匹配算法.BM算法在最坏情况下可以做到线性的,平均情况下是亚线性的(即 ...

  8. 字符串匹配算法(三):KMP(KnuthMorrisPratt)算法

    文章目录 KMP 原理 next数组的构建 代码实现 KMP 一提到字符串匹配算法,想必大家脑海中想到的第一个必然就是KMP算法,KMP算法的全称叫做KnuthMorrisPratt算法,与上一篇博客 ...

  9. 【数据结构与算法】字符串匹配 BM算法

    单模式串匹配 BF 算法和 RK 算法 BM 算法和 KMP 算法 多模式串匹配算法 Trie 树和 AC 自动机 BM算法 BM算法的核心思想是通过将模式串沿着主串大踏步的向后滑动,从而大大减少比较 ...

  10. diff算法阮一峰_【重学数据结构与算法(JS)】字符串匹配算法(三)——BM算法

    前言 文章的一开头,还是要强调下字符串匹配的思路 将模式串和主串进行比较 从前往后比较 从后往前比较 2. 匹配时,比较主串和模式串的下一个位置 3. 失配时, 在模式串中寻找一个合适的位置 如果找到 ...

最新文章

  1. BM提供支持云的量子计算平台,以加速创新
  2. JVM第三篇 — JVM是怎么工作的?
  3. nginx 路由配置
  4. python文件存储过程_python调用MySql存储过程
  5. Android属性动画 实战-视差动画
  6. Java8新特性解析
  7. gradle和maven区别
  8. Bad owner or permissions on .ssh/config win10问题解决
  9. [开源]quakeIII(雷神之锤3)源码
  10. codevs 1683 车厢重组
  11. JAVA调用海康威视SDK
  12. java 拼音_JAVA实现汉字转换为拼音 pinyin4j/JPinyin
  13. java基础篇(10) 可变参数列表介绍
  14. qpieseries显示百分比_为饼图添加百分比显示效果
  15. 常用的人脸检测识别等数据集百度云下载
  16. 初创的云平台公司是否需要设立运维岗
  17. matlab 条件方程组的解,Matlab带约束条件的非线性方程组求解
  18. Worthington 核糖核酸酶 T1解决方案
  19. RK3399 Android7.1 充电芯片bq25723发生ACOV后引起系统黑屏死机
  20. 游戏开发41课 unity 目录分析

热门文章

  1. 【智能家居v1.0项目】C#实现scoket通信
  2. 那些令人喷饭的代码注释:仅以此代码献给...it's realy ?
  3. 只能在执行Render() 的过程中调用 RegisterForEventValidation;
  4. http | 状态码
  5. oracle切换实例启动,3.1 Oracle体系结构之实例启动与关闭
  6. 三路划分快速排序 java_程序员面试—快速排序的三路划分
  7. python调用接口获取文件_Python中做接口自动化如何读取配置ini文件
  8. Mysql之事务与视图
  9. python or的用法_python and or用法详解
  10. DCL记忆上次输入值lisp_python-输入和输出