前言

文章的一开头,还是要强调下字符串匹配的思路

  1. 模式串主串进行比较
  • 从前往后比较
  • 从后往前比较

2. 匹配时,比较主串模式串的下一个位置
3. 失配时,

  • 模式串中寻找一个合适的位置

    • 如果找到,从这个位置开始与主串当前失配位置进行比较
    • 如果未找到,从模式串的头部与主串失配位置的下一个位置进行比较
  • 主串中找到一个合适的位置,重新与模式串进行比较

前面的 BFKMP 算法,都是属于规规矩矩从前向后的操作,后者仅在寻找模式串的合适位置上进行了优化,而 BM 算法的操作就显得骚了很多,它的优化点在于: 1. 从后往前比较 2. 失配时,寻找的是主串中合适的位置

算法介绍与分析

关于算法的介绍和分析,网上有很多解释,这里推荐一下阮一峰的字符串匹配的Boyer-Moore算法,很清楚的讲解了整个优化的思路,可以先看完理解了再往下看,因为下面主要介绍一下坏字符规则好后缀规则需要的数据结构的手工求法以及代码实现。

坏字符规则

运用坏字符规则,在算法里主要体现在生成一张散列表,表的key值是字符集里每个字符的ASCII码值,value值是模式串中该字符的位置,举个栗子:

假设字符串的字符集不是很大,用长度为256的数组来存储,并且初值赋值为-1。数组的下标对应字符的 ASCII 码值,数组中存储这个字符在模式串中出现的位置。这里要特别说明一点,如果坏字符在模式串里多处出现,选择最靠后的那个,因为这样不会让模式串滑动过多,导致本来可能匹配的情况被滑动略过。

好后缀规则

好后缀规则体现在如何求出 suffixprefix 两个数组以及移动规则

suffix 数组

key值表示的是后缀子串的长度,value值表示的是在模式串中跟好后缀 S 相匹配的最后一个子串 S' 的首字母在模式串中的key值,如下图:

prefix 数组

同样的,key值表示的是后缀子串的长度,而value值表示的是模式串中,是否有和该长度下后缀子串相同的前缀子串,是的话为 true,否则为 false,如下图:

移动规则

移动规则总结如下

  • 模式串中寻找跟好后缀 S 相匹配的最后一个子串 S'
  • 如果找到,将模式串移动到使得 S' 和主串对齐的位置
  • 如果找不到,再寻找模式串前缀子串中是否有和 好后缀 S后缀子串匹配的位置,滑动模式串以对齐。
  • 如果仍然找不到,则将模式串移动至主串模式串末尾对齐的下一个位置

下图分别对应三种情况:

代码实现

整体逻辑框架

参考字符串匹配的思路

  1. 仍然需要进行主串模式串的字符对比,所以需要两个指针 ij 分别指向主串模式串,记录位置 需要一个循环来重复进行匹配操作,此时思考终止条件:

    1. i 指向主串每次匹配的合适位置,从前往后扫描;j 指向模式串的尾部,从后往前扫描。考虑极端情况:主串模式串对比完,仍然无法匹配。此时,i 的位置一定小于等于 主串长度 n模式串长度 m 的差值。具体可看下图。
  2. 每次模式串从后往前与主串进行匹配,这也需要一个内层循环来驱动指针j 如果匹配,只需要继续移动匹配位置即可
  3. 如果失配,分别根据坏字符规则好后缀规则计算出 i 需要移动的位置,选择两个值当中最大的,重新计算 i 的值,重复进行匹配。

根据以上分析可以写出整个的逻辑框架代码:

框架写好后,接下来就是完善三个辅助函数即可

求坏字符散列表

这个就没有什么可以多说的了,只要参考上面分析的,一步一步写出代即可:

求好后缀记录数组 suffixprefix

拿下标从 0i 的子串(i 可以是 0m-2)与整个模式串,求公共后缀子串。如果公共后缀子串的长度是 k,那就记录 suffix[k]=jj 表示公共后缀子串的起始下标)。如果 j 等于 0,也就是说,公共后缀子串也是模式串的前缀子串,就记录 prefix[k]=true。可以自己动下手,模拟下代码的运行,尤其注意中k值的运用,很巧妙。

求好后缀移动步数

根据上面此步的算法分析,也可以写出:

总结

总的来说,BM算法另辟蹊径,通过从后往前的匹配的思路,加上坏字符规则好后缀规则来优化移动的步数,从而提高算法的匹配效率。

后记

“字符串匹配算法”是“重学数据结构与算法”系列笔记:

  • 字符串匹配算法(一)——BF算法
  • 字符串匹配算法(二)——KMP算法
  • 字符串匹配算法(三)——BM算法
  • 字符串匹配算法(四)——Sunday算法

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

  1. 大量的数据做字符串匹配_【重学数据结构与算法(JS)】字符串匹配算法(三)——BM算法...

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

  2. 字符串匹配算法之BM算法

    BM算法,全称是Boyer-Moore算法,1977年,德克萨斯大学的Robert S. Boyer教授和J Strother Moore教授发明了一种新的字符串匹配算法. BM算法定义了两个规则: ...

  3. 一看就懂的字符串匹配算法 之 BM算法

    先来一个导读,关于BM算法开始有了难度,大家一定要静下心,咬着呀也得给我读下去,这样你才能有收获. 我们在文本编辑器中,我们经常用到查找及替换功能.比如说,在Word文件中,通过查找及替换功能,可以把 ...

  4. 利用双向循环链表实现长整数的存储_重学数据结构之链表篇

    本文是重新数据结构系列文章的第二篇,本文和大家一起探讨链表的相关知识. 链表是怎么样的数据结构 链表,不需要连续的内存空间,通过"指针(引用)"将一组零散的内存块串联起来的数据结构 ...

  5. 重学数据结构与算法(02)--将时间复杂度转换成空间复杂度

    将时间复杂度转换成空间复杂度 1)时间昂贵.空间廉价 2)数据结构连接时空 3)降低复杂度的案例 例一 例二 4)总结 面试的过程中,常常会遇到考察手写代码的场景,通常面试官会追问:"这段代 ...

  6. 重学数据结构——快速排序,二分法查找

    每次提起快排,内心中都有点隐隐作痛. 当时腾讯的那个面试官让我写快排的前两遍排序结果,结果,我当时居然没写上来-- 这个,就是所谓的关键时刻掉链子吧,这么经典的快排都不会,真是丢死人了-- 今天在实验 ...

  7. 字符串匹配算法:Horspool算法

    Horspool 字符串匹配算法对Boyer-Moore算法的简化算法. Horspool 算法是一种基于后缀匹配的方法,是一种"跳跃式"匹配算法,具有sub-linear亚线性时 ...

  8. 判断字符串 正则_(重学前端 - JavaScript(模块一)) 14、引用类型之 RegExp (正则)(详述)...

    上一篇文章介绍了 JavaScript 中的 Date 类型,从地理方面的原理知识开始入手,如果大家认真看过上一篇文章,相信 JavaScript 中的 Date 类型已经难不住大家了!!! 但是今天 ...

  9. http 阮一峰_互联网协议入门(二)

    上一篇文章分析了互联网的总体构思,从下至上,每一层协议的设计思想. 这是从设计者的角度看问题,今天我想切换到用户的角度,看看用户是如何从上至下,与这些协议互动的. ================== ...

最新文章

  1. 马上开始写 react ES6 --- 基于gulp 和 Babel 的脚手架
  2. 外网访问FTP出错200 Type set to A
  3. 子弹图(Bullet chart)绘制很难吗?绘制技巧整理送你~~
  4. 谓词::不适合Java
  5. C# winform 窗体怎么隐藏标题栏,不显示标题栏
  6. 求出数组中元素的总和_数组中所有元素的总和可被给定数K整除
  7. 【flink】95-260-045-源码-检查点-CheckPoint
  8. rss阅读器 java_RSS阅读器
  9. merkle tree(hash tree)
  10. Notepad++相关插件
  11. Andromeda OS 来了,Android 再见?
  12. 半正定矩阵的对角元素不小于该矩阵的最小特征值
  13. Stimulsoft Reports.Web 2022.2.3 Crack
  14. 量子恒道统计-淘宝添加步骤
  15. UWB定位系统的主要误差来源
  16. EXCEL公式系列:方差、标准差
  17. win10计算机停止工作,360重装Win10系统后如何应对已停止工作提示的办法
  18. girl_noise.jpg恢复去噪
  19. C# 获取某个时间的0点0分和23点59分59秒
  20. Flutter必备——Dart入门(上)

热门文章

  1. A-Frame WEB VR框架初体验
  2. python图片保存为txt文件_python + opencv实现提取png图像的像素信息并存储到txt文件中(附安装指导)...
  3. 智能客户端ios_为什么现在的客户端开发越来越不吃香了
  4. sockaddr类型重定义
  5. 蜂窝注册表和永久存储
  6. python10的因数_十五道Python小案例,学会这些,Python基础已过关!
  7. python导出dxf图_在PDMS中使用python直接生成管口方位图(开源分享第三集)
  8. mysql客户端保存数据乱码_mysql客户端数据乱码问题
  9. 【转】C# 网络连接中异常断线的处理:ReceiveTimeout, SendTimeout 及 KeepAliveValues(设置心跳)
  10. WebDAV, IIS, 和SharePoint之间的关系