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

d1e38a6fff32221d5e7b97189e3f4a66.png

前言

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

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


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

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

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

算法介绍与分析

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

坏字符规则

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

fa7aba71dc084f8e03bfc4f0673e4254.png

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

好后缀规则

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

suffix 数组

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

22ea58a0864f6c36f162e2ae1ca4ce49.png

prefix 数组

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

569286d7a67f58eeaa1baafd95a26d1d.png

移动规则

移动规则总结如下

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

下图分别对应三种情况:

b2006052fcf14ae06e99b83833904a32.png

66a65d8d86c0d972d44d1fa05dea25ed.png

f7ccb9f60d1db44906d211c544236ece.png

代码实现

整体逻辑框架

参考字符串匹配的思路

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

ec50bf934bf21ceeae232b83eb2062a3.png

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

4749888be49776f8ae4b33c28d2f7bbc.png

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

求坏字符散列表

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

e1866ea5e0d34677d729bc22394df7ea.png

求好后缀记录数组 suffixprefix

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

b8b3ec450826152ff498b915b3a0a714.png

求好后缀移动步数

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

1ffb8c377c0cee85d78682859aec01eb.png

总结

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

后记

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/443237.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

远程mysql定时删除数据_mysql定时备份数据库 删除历史文件 将备份数据库传送到另外服务器...

定时备份数据库脚本并压缩删除历史文件1.创建备份脚本vim mysql-backup.sh#!/bin/bashbakdate %y-%m-%d-%Htool/usr/local/mysql/bin/mysqldump$tool -uroot -p密码 --lock-all-tables --all-databases | gzip > /路径/$bak\.sql.gzfind 路径 -name "name_*.sql.gz&q…

python input 拖入路径 去除转义 空格_python学习笔记(基础-2)(转载)

1.输出用print()在括号中加上字符串,就可以向屏幕上输出指定的文字。2.输入如果要让用户从电脑输入一些字符怎么办?Python提供了一个input(),可以让用户输入字符串,并存放到一个变量里。输入是Input,输出是Output&…

mysql和mdy_Liunx下安装MySql

1.安装数据库:执行命令 yum -y install mysql-server2.启动数据库:安装完毕,执行命令service mysqld start3.登录数据库:mysql -u root -p回车后输入密码(mysql的默认用户名是root,密码为空)4.使用数据库:登…

python websocket服务器https_Socket与WebSocket以及http与https重新总结

Socket与WebSocket以及http与https重新总结一.Socket网络中的Socket是一个抽象的接口 ,而是为了方便使用TCP或UDP而抽象出来的一层 ,可以理解为网络中连接的两端。通常被叫做套接字接口.二.WebSocketWebSocket就是其中一种,是为了创建一种双向…

python微博评论爬虫_详解用python写网络爬虫-爬取新浪微博评论 基于Python的新浪微博爬虫研究...

怎样爬取新浪微博的评论信息针对八爪鱼在微博的应用上,除了用户信息之外还包括话题内容方面的采集,目前绝大多数企业均在微博设有官方微博,八爪鱼可以协助企业快速及时的抓取与企业产品相关联的话题信息,规则市场内有配置好的规则…

韩顺平 mysql sqlhelper类_(最全)韩顺平jsp购物车源代码(包含数据库)

【实例简介】韩顺平的jsp购物车项目,所有源码都在,包含数据库,是网络上最全的【实例截图】【核心代码】myshopping└── myshopping├── myshopping│ ├── src│ │ ├── com│ │ │ └── hsp│ │ │ ├── domain│ │ │ │ ├── B…

c#和python更适合爬虫_python在爬虫方面有哪些优势呢?

python是一门非常不错的编程语言,通俗易懂、适合零基础入门,尤其是爬虫领域有着独特的优势,成为了首选编程语言。Python是一种计算机程序设计语言,是一种动态的、面向对象的脚本语言。Python最初被设计用于编写自动化脚本(shell)&…

mysql创建独立表空间_InnoDB独立表空间

在查看MySQL的数据库文件的时候会发现,MyISAM存储引擎类型的表会有三个文件,*.frm,*.MYD,*.MYI,但是InnoDB存储引擎的文件只有一个*.frm,原来是因为InnoDB没有开启独立表空间,执行如下命令可以看到:mysql&g…

python os模块方法_python os模块方法总结

在python中os是一个非常常用的模块,下面是对os中方法的总结(实验为Mac环境)1 . os.name :输出字符串指示使用的平台,windows是nt, linux/unix/mac是posix>>> os.nameposix>>>2 . os.getcwd() :获取当前目录>>> …

java button中文乱码_java解决中文乱码的几种写法

工作中总会遇到中文乱码问题,以导出文件,文件名称是中文的话,下载下来的文件名称会乱码问题,总结了几种解决文件名乱码的写法,仅供参考。首先定义一个汉语字符串String zhName "错误码模板";一、java.net.U…

java jframe添加面板_JFrame添加组件的两种方式

对JFrame添加组件有两种方式:1) 用getContentPane()方法获得JFrame的内容面板,再对其加入组件:frame.getContentPane().add(childCompontent)常分开来写Container containergetContentPanel();(隐式的this.getContentPanel()) ;得到jframe的内…

java 德生读卡器对接程序_德生TSW-F4 社保卡读卡器.rar

【实例简介】德生TSW-F4 社保卡读卡器测试程序以及动态库,出厂自带程序【实例截图】【核心代码】b79d6d98-2fcb-4e20-ab26-8f7aa14b320c└── 德生TSW-F4 社保卡读卡器├── TSW-F4 U系列读写器随机软件_20120907│ ├── Dll│ │ ├── F4.h│ │ ├…

ios 数组越界奔溃库_iOS中防止数组越界之后发生崩溃

在iOS开发中有时会遇到数组越界的问题,从而导致程序崩溃。为了防止程序崩溃,我们就要对数组越界进行处理。通过上网查资料,发现可以通过为数组写一个分类来解决此问题。基本思路:为NSArray写一个防止数组越界的分类。分类中利用ru…

java map与set的区别_Java中的Set,List,Map的区别是什么?

对JAVA的集合的理解是想对于数组数组是大小固定的,并且同一个数组只能存放类型一样的数据(基本类型/引用类型)JAVA集合可以存储和操作数目不固定的一组数据。所有的JAVA集合都位于 java。util包中!JAVA集合只能存放引用类型的的数据,不能存放…

java怎么使用泛型_java泛型 7 泛型的基本介绍和使用

现在开始深入学习Java的泛型了,以前一直只是在集合中简单的使用泛型,根本就不明白泛型的原理和作用。泛型在java中,是一个十分重要的特性,所以要好好的研究下。一、泛型的基本概念泛型的定义:泛型是JDK 1.5的一项新特性…

java铝轮_为速度而生 JAVA Fuoco铝合金气动公路

人类在追求速度的历史上一直在不断创新,从两个轮子的自行车,到四个轮字的汽车,再到螺旋桨的飞机,追求速度是人类与生俱来的天性。就如同公路车的用途非常多,综合型公路车、耐力型公路车、爬坡型公路车,但唯…

erlang mysql性能瓶颈,Erlang Mysql:如何防止SQL注入

Im very new to erlang and I need to code something which inserts rows in a MySQL Database.How can I prevent SQL Injections with Erlang? Is there also something like prepared statements in other Languages or how should I do it?Thanks for your replies.解决…

下列哪个不是java的数据类型_下面哪个不是Java基本数据类型?()

采集血标本时,错误的操作是A.血清标本应注入干燥试管B.生化检验标本在空腹时采集试比较脂肪酸β-氧化与生物合成的差异。调节水平衡的激素主要是A.胰岛素 B.甲状旁腺激素 C.血管升压素 D求比50克多5克的数是多少?列式是…

Java jpa 字段限制_Java-JPA:仅更新特定字段

我有同样的问题,正如Deinum先生所指出的,答案是否定的,您不能使用save。 主要问题是Spring Data不知道如何处理null。 是否设置了空值,还是因为需要将其删除而设置了空值?现在从您的问题来看,我认为您也有同…

java excel中删除两列_Java 插入、隐藏/显示、删除Excel行或列

概述操作Excel工作表时,对表格中的行或列数据可执行,包括插入、隐藏、显示、删除等在内的多种操作需求,本文将通过Java代码示例演示每种操作的具体实现方法。文中方法使用了Java Excel类库(Free Spire.XLS for Java 免费版),可通过…