字符串匹配的 Boyer-Moore 算法

各种文本编辑器的” 查找” 功能(Ctrl+F),大多采用 Boyer-Moore 算法。

下面,我根据 Moore 教授自己的例子来解释这种算法。。

假定字符串为”HERE IS A SIMPLE EXAMPLE”,搜索词为”EXAMPLE”。

       首先,” 字符串” 与” 搜索词” 头部对齐,从尾部开始比较。
       这是一个很聪明的想法,因为如果尾部字符不匹配,那么只要一次比较,就可以知道前 7 个字符肯定不是要找的结果。
       我们看到,”S” 与”E” 不匹配。这时,“S” 就被称为” 坏字符”(bad character),即不匹配的字符。我们还发现,”S” 不包含在搜索词”EXAMPLE” 之中,这意味着可以把搜索词直接移到”S” 的后一位。

       依然从尾部开始比较,发现”P” 与”E” 不匹配,所以”P” 是” 坏字符”。但是,”P” 包含在搜索词”EXAMPLE” 之中。所以,将搜索词后移两位,两个”P” 对齐。

       我们由此总结出 “坏字符规则”:
       后移位数 = 坏字符的位置 – 搜索词中的上一次出现位置
       如果” 坏字符” 不包含在搜索词之中,则上一次出现位置为 -1。
       以”P” 为例,它作为” 坏字符”,出现在搜索词的第 6 位(从 0 开始编号),在搜索词中的上一次出现位置为 4,所以后移 6 – 4 = 2 位。再以前面第二步的”S” 为例,它出现在第 6 位,上一次出现位置是 -1(即未出现),则整个搜索词后移 6 – (-1) = 7 位。

       依然从尾部开始比较,”E” 与”E” 匹配。

       比较前面一位,”LE” 与”LE” 匹配。

       比较前面一位,”PLE” 与”PLE” 匹配。

       比较前面一位,”MPLE” 与”MPLE” 匹配。我们把这种情况称为” 好后缀”(good suffix),即所有尾部匹配的字符串。注意,”MPLE”、”PLE”、”LE”、”E” 都是好后缀。

       比较前一位,发现”I” 与”A” 不匹配。所以,”I” 是” 坏字符”。

       根据” 坏字符规则”,此时搜索词应该后移 2 – (-1)= 3 位。问题是,此时有没有更好的移法?

       我们知道,此时存在”好后缀”。所以,可以采用 “好后缀规则”:
       后移位数 = 好后缀的位置 – 搜索词中的上一次出现位置
       计算时,位置的取值以” 好后缀” 的最后一个字符为准。如果” 好后缀” 在搜索词中没有重复出现,则它的上一次出现位置为 -1。
       所有的” 好后缀”(MPLE、PLE、LE、E)之中,只有”E” 在”EXAMPLE” 之中出现两次,所以后移 6 – 0 = 6 位。

       可以看到,” 坏字符规则” 只能移 3 位,” 好后缀规则” 可以移 6 位。所以,Boyer-Moore 算法的基本思想是,每次后移这两个规则之中的较大值。
       更巧妙的是,这两个规则的移动位数,只与搜索词有关,与原字符串无关。因此,可以预先计算生成《坏字符规则表》和《好后缀规则表》。使用时,只要查表比较一下就可以了。

       继续从尾部开始比较,”P” 与”E” 不匹配,因此”P” 是” 坏字符”。根据” 坏字符规则”,后移 6 – 4 = 2 位。

       从尾部开始逐位比较,发现全部匹配,于是搜索结束。如果还要继续查找(即找出全部匹配),则根据” 好后缀规则”,后移 6 – 0 = 6 位,即头部的”E” 移到尾部的”E” 的位置。

https://greedysky.github.io/2016/09/01/%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8C%B9%E9%85%8D%E7%9A%84%20Boyer-Moore%20%E7%AE%97%E6%B3%95/

时间: 2024-10-12 23:33:22

字符串匹配的 Boyer-Moore 算法的相关文章

模式字符串匹配问题(KMP算法)

这两天又看了一遍<算法导论>上面的字符串匹配那一节,下面是实现的几个程序,可能有错误,仅供参考和交流. 关于详细的讲解,网上有很多,大多数算法及数据结构书中都应该有涉及,由于时间限制,在这就不重复了. 需要说明的是: stra:主串,及需要从中寻找模式串的字符串 strb:模式串 <算法导论>上面包括严蔚敏老师<数据结构>,字符串下表是按从1开始,并且<数据结构>一书中貌似吧字符串的第一个字符用来储存字符串长度.这里我改成了0. maxlen :字符串的最长

字符串匹配的三种算法

下面将介绍三种有关字符串匹配的算法,一种是朴素的匹配算法,时间复杂度为O(mn),也就是暴力求解.这种方法比较简单,容易实现.一种是KMP算法,时间复杂度为O(m+n),该算法的主要任务是求模式串的next数组.另外还有一种对KMP算法的改进,主要是求nextval数组. 第一种朴素的匹配算法: int index(char str[], char subStr[]) { int i = 0, j = 0,index = 0; while (str[i] != '\0' && subStr

Boyer Moore算法(字符串匹配)

上一篇文章,我介绍了KMP算法. 但是,它并不是效率最高的算法,实际采用并不多.各种文本编辑器的"查找"功能(Ctrl+F),大多采用Boyer-Moore算法. Boyer-Moore算法不仅效率高,而且构思巧妙,容易理解.1977年,德克萨斯大学的Robert S. Boyer教授和J Strother Moore教授发明了这种算法. 下面,我根据Moore教授自己的例子来解释这种算法. 1. 假定字符串为"HERE IS A SIMPLE EXAMPLE",搜

字符串匹配问题【KMP算法】

一.问题 给定两个字符串S和T,找出T在S中出现的位置. 二.朴素算法 当S[i] != T[j]时,把T往后移一位,回溯S的位置并重新开始比较.    (1) 成功匹配的部分(ABC)中,没有一样的字符 S: i A B C A B C E T: j A B C E       S: i A B C A B C E T: j   A B C E     S: i A B C A B C E T: j     A B C E   S: i A B C A B C E T: j       A B

字符串匹配(KMP)算法及Java实现

一.什么是KMP算法? 维基百科的解释是:在计算机科学中,Knuth-Morris-Pratt字符串查找算法(简称为KMP算法)可在一个主文本字符串S内查找一个词W的出现位置.此算法通过运用对这个词在不匹配时本身就包含足够的信息来确定下一个匹配将在哪里开始,从而避免重新检查先前已经匹配过的字符. 二.字符串的前缀与后缀 前缀:字符串除了最后一个字符的全部头部组合: 后缀:字符串处理第一个字符的全部头部组合:例如 三.字符串部分匹配表 "部分匹配"的实质是,有时候,字符串头部和尾部会有重

字符串匹配(三)----后缀数组算法

一.什么是后缀数组: 字符串后缀Suffix 指的是从字符串的某个位置开始到其末尾的字符串子串.后缀数组 Suffix Array(sa) 指的是将某个字符串的所有后缀按字典序排序之后得到的数组,不过数组中不直接保存所有的后缀子串,只要记录后缀的起始下标就好了. 比如下面在下面这张图中,sa[8] = 7,表示在字典序中排第9的是起始下标为7的后缀子串,这里还有一个比较重要的数组rank,rank[i] : sa[i]在所有后缀中的排名 ,比如rk[5]=0,表示后缀下标为5的子串在后缀数组中排

字符串匹配的几种算法

字符串匹配算法:找到子串在原字符串中第一次出现的位置 字符串A:abcabcabcabc 字符串B:bca 1.朴素字符串匹配算法 假设有两个指针,一个i指向字符串A的起始位置,一个j指向字符串B的起始位置: (1)若A[I]==B[j],则i++;j++ (2)在(1)的情况下,若A[i]!=A[j],则j=0,i回到A字符串的上一次的起始位置. 缺点:不适用于那种多个相同的,不能找到第一个相同的位置. int string_match(char*str1, char*str2) { int

字符串匹配(BF,BM,Sunday,KMP算法解析)

字符串匹配一直是计算机领域热门的研究问题之一,多种算法层出不穷.字符串匹配算法有着很强的实用价值,应用于信息搜索,拼写检查,生物信息学等多个领域. 今天介绍几种比较有名的算法: 1. BF 2. BM 3. Sunday 4. KMP -,BF算法 BF(Brute Force)算法又称为暴力匹配算法,是普通模式匹配算法. 其算法思想很简单,从主串S的第pos个字符开始,和模式串T的第一个字符进行比较,若相等,则主串和模式串都后移一个字符继续比较:若不相同,则回溯到主串S的第pos+1个字符重新

字符串匹配系列算法

问题描述: 在匹配串中寻找模式串,如: 匹配串:THIS IS A SIMPLE EXAMPLE 模式串(搜索词):EXAMPLE 算法1:Brute Force算法(蛮力搜索法) 首先将匹配串和模式串左对齐,然后从左向右一个一个进行比较,如果不成功则模式串向右移动一个单位. 算法2:Karp Rabin算法 模式串:pattern="pappar",长度记为pattern_len 文本串:text="pappappapparrassanuaragh" 预备阶段就是

[算法系列之十四]字符串匹配之Morris-Pratt字符串搜索算法

前言 我们前面已经看到,蛮力字符串匹配算法和Rabin-Karp字符串匹配算法均非有效算法.不过,为了改进某种算法,首先需要详细理解其基本原理.我们已经知道,暴力字符串匹配的速度缓慢,并已尝试使用Rabin-Karp中的一个散列函数对其进行改进.问题是,Rabin-Karp的复杂度与强力字符串匹配相同,均为O(mn). 我们显然需要采用一种不同方法,但为了提出这种不同方法,先来看看暴力字符串匹配有什么不妥之处.事实上,再深入地研究一下它的基本原理,就能找到问题的答案了. 在暴力匹配算法中,需要检