串匹配算法最常用的情形是从一篇文档中查找指定文本。需要查找的文本叫做模式串,需要从中查找模式串的串暂且叫做查找串吧。

BM算法好后缀规则

公式:

对于长度为m的模式串P,在i处失配时,模式串向前滑动的距离next[i]等于:
next[i]= { 1;        i = m;
           i-k+1;   存在最大的K (1 <= k <= i),使得 PkPk+1..Pk+m-i-1 == Pi+1Pi+2..Pm 且Pk-1 != Pi     =>case 1
           m-k;     存在最大的K (1 <= k <= m-i),使得 P1P2..Pk == Pm-k+1..Pm-1Pm       =>case 2
           m;        其他情况;       =>case 3 }

下面是图示解析(图来自http://www.tuicool.com/articles/nqqE3uU,下面是少有图绘制正确的解析):

三种情形一张图表示

可以看出好后缀规则和kmp算法有点像,kmp是从左向右有自匹配的话能减少一些比较,bm算法是从右向左有自匹配的话能减少一些比较。下面代码的思路就是先求出自匹配长度,再求移动距离。好后缀规则的代码,是Python的,直接从源代码执行的语言用来写算法很方便。这里求自匹配的代码是优化过的,优化算法参考Boyer- Moore算法百度百科。

def suffix(s):
    """
    suff[i] = k, the length of the longest suffix of s[:i](the sub string of s ending at i)
    that matches a suffix of s (the sub string of s ending at len(s)-1)
    """
    m=len(s)
    g = m-1
    suff = {}
    suff[g]=m

    for i in range(m-2,-1,-1):
        if(i>g and suff[m-1-f+i]<i-g):
            suff[i] = suff[m-1-f+i]
        else:
            if(i<g):
                g = i
            f = i
            while(g>=0 and s[g]==s[m-1-f+g]):
                g-=1
            suff[i] = f - g

    return suff

def PreBmGs(s):
    m = len(s)
    suff = suffix(s)
    bmGs = {}
    for i in range(0,m,1):
        bmGs[i] = m

    for i in range(m-1,-1,-1):
        if(i+1 == suff[i]):
            for j in range(0,m-1-i,1):
                if(m == bmGs[j]):
                    bmGs[j] = m-1-i;

    for i in range(0,m-1,1):
        bmGs[m - 1 - suff[i]] = m - 1 - i;

    return bmGs;

坏字符规则

当模式串与查找串在某个位置失配,查找串失配位置的字符叫做坏字符。单独能实现匹配的坏字符规则是:将模式串失配位置左侧最靠近失配位置的坏字符和查找串的失配位置对齐;如果模式串失配位置左侧不包含坏字符,那么将模式串头部对齐坏字符下一个(右侧)位置。实际上的坏字符规则比这个要简单,模式串最右侧的坏字符和查找串的失配位置对齐;如果模式穿不包含坏字符,那么将模式串头部对齐坏字符下一个(右侧)位置。下图的公示就包含了这两种情况了。

由于坏字符规则不是在模式串失配位置左侧字串中应用的,所以会出现将模式串向回移动的情况。由于有好后缀规则,这种失效的情况可以被避免。

def PreBmBc(s):
    m = len(s)
    bmBc = {}
    for i in range(0,m-1,1):
        bmBc[s[i]] = i;

    return bmBc;

BM算法匹配源码

def BoyerMoore(s,p):
    m = len(p)
    n = len(s)
    bmBc = PreBmBc(p)
    bmGs = PreBmGs(p)
    j = 0
    while(j <= n-m):
        i = m-1
        while(i>=0 and p[i]==s[j+i]):
            i -= 1
        if(i < 0):
            'Find, next fint start at j+bmGs[0]'
            return j
        else:
            bc = -1
            if(bmBc.has_key(s[j+i])):
                bc = bmBc[s[j+i]]
            j += max(bmGs[i],i-bc)

    return -1

BM算法的其他解析

http://www-igm.univ-mlv.fr/~lecroq/string/node14.html

这个地方给出的C语言代码和上面的python代码一样的方式优化了。

http://www.inf.fh-flensburg.de/lang/algorithmen/pattern/bmen.htm

这个地方给出的C代码根据上面的规则直接暴力解决。

BM串匹配算法的更多相关文章

  1. KMP串匹配算法解析与优化

    朴素串匹配算法说明 串匹配算法最常用的情形是从一篇文档中查找指定文本.需要查找的文本叫做模式串,需要从中查找模式串的串暂且叫做查找串吧. 为了更好理解KMP算法,我们先这样看待一下朴素匹配算法吧.朴素 ...

  2. 串匹配算法讲解 -----BF、KMP算法

      参考文章: http://www.matrix67.com/blog/archives/115     KMP算法详解 http://blog.csdn.net/yaochunnian/artic ...

  3. 串匹配算法之BM算法

    参考资料: http://blog.csdn.net/eric491179912/article/details/6210009   http://blog.163.com/pengfeicui@ye ...

  4. 【数据结构】 字符串&KMP子串匹配算法

    字符串 作为人机交互的途径,程序或多或少地肯定要需要处理文字信息.如何在计算机中抽象人类语言的信息就成为一个问题.字符串便是这个问题的答案.虽然从形式上来说,字符串可以算是线性表的一种,其数据储存区存 ...

  5. 算法 | 串匹配算法之KMP算法及其优化

    主串 s:A B D A B C A B C 子串 t:  A B C A B 问题:在主串 s 中是否存在一段 t 的子串呢? 形如上述问题,就是串匹配类问题.[串匹配--百度百科] 串匹配问题是一 ...

  6. 经典串匹配算法(KMP)解析

    一.问题重述 现有字符串S1,求S1中与字符串S2完全匹配的部分,例如: S1 = "ababaababc" S2 = "ababc" 那么得到匹配的结果是5( ...

  7. Sunday串匹配算法 C语言实现

    unsigned char * sunday( void * a_buf1, unsigned int len1, void * a_buf2, unsigned int len2 ){ unsign ...

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

    unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...

  9. 算法——字符串匹配之BM算法

    前言 Boyer-Moore算法是一种基于后缀匹配的模式串匹配算法(简称BM算法),后缀匹配就是模式串从右到左開始比較,但模式串的移动依旧是从左到右的.在实践中.BM算法效率高于前面介绍的<KM ...

随机推荐

  1. Html5中的跨页面消息传输

    1.如果要接受从其他的窗口那里发过来的消息,就必须对窗口对象的message事件进行监控. window.addEventListener("message",function() ...

  2. Dephi的同一个线程支持累次Execute吗

    Suspend放到循环里------解决方案--------------------执行完不结束只休眠.另外还需要线程池.------解决方案--------------------    while ...

  3. Flask + Gunicorn + Nginx 部署

    最近很多朋友都在问我关于 Flask 部署的问题,说实在的我很乐意看到和回答这样的问题,至少证明了越来越多人开始用 Flask 了. 之前我曾发表过一篇在 Ubuntu 上用 uwsgi + ngin ...

  4. ArcGIS Engine 下投影坐标和经纬度坐标的相互转换

    ArcGIS Engine 下投影坐标和经纬度坐标的相互转换 投影转经纬度 ); pPoint.Project(pSRF.CreateGeographicCoordinateSystem((int)e ...

  5. 【Unity Shaders】学习笔记——渲染管线

    [Unity Shaders]学习笔记——Shader和渲染管线 转载请注明出处:http://www.cnblogs.com/-867259206/p/5595924.html 写作本系列文章时使用 ...

  6. Nodejs文件服务器

    最近一直在忙于一个比较大的项目,在项目中需要有个文件服务器来支持.老鸟们建议我去用NodeJs来实现,我在接手这个项目之前其实并不了解NodeJs,但是一直想去了解.借着这个机会好好去学习一下.下面是 ...

  7. java springMVC生成二维码

    Zxing是Google提供的工具,提供了二维码的生成与解析的方法,现在使用Java利用Zxing生成二维码 1),二维码的生成 将Zxing-core.jar 包加入到classpath下. 我的下 ...

  8. 图的最短路算法 Bellman-Ford

    BF求图的最短路径的时间复杂度是O(MN),这样的时间复杂度并不比迪杰斯特拉算法好,但是BF算法支持图中存在负权的情况,但图中不能存在负圈,因为如果存在负圈,最短路是不存在的,因此BF算法的另一个重要 ...

  9. Software: MPEG-7 Feature Extraction Library

    Software MPEG-7 Feature Extraction Library : This library is adapted from MPEG-7 XM Reference Softwa ...

  10. 动态链接库(dll) __declspec(dllimport) __declspec(dllexport)

    一. __declspec(dllexport) Microsoft 在 Visual C++ 的 16 位编译器版本中引入了 __export,使编译器得以自动生成导出名并将它们放到一个 .lib ...