zoukankan      html  css  js  c++  java
  • BM串匹配算法

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

    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;
    View Code

    坏字符规则

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

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

    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代码根据上面的规则直接暴力解决。

  • 相关阅读:
    用Visual Studio2010 编译 C++文件"hello world”
    hdu 1010 Tempter of the Bone(dfs+奇偶剪枝)
    最长子串(动态规划)
    C++中,访问字符串的三种方法
    POJ3260:The Fewest Coins(混合背包)
    如何做好基层技术管理工作?
    UVa10651(记忆化搜索)
    <Win32_5>深入浅出Win32的计时器
    【转载】一步一步写算法(之hash表)
    C可变参数函数 实现
  • 原文地址:https://www.cnblogs.com/tgis/p/4766657.html
Copyright © 2011-2022 走看看