zoukankan      html  css  js  c++  java
  • Boyer–Moore (BM)字符串搜索算法

    计算机科学里,Boyer-Moore字符串搜索算法是一种非常高效的字符串搜索算法。它由Bob BoyerJ Strother Moore设计于1977年。此算法仅对搜索目标字符串(关键字)进行预处理,而非被搜索的字符串。虽然Boyer-Moore算法的执行时间同样线性依赖于被搜索字符串的大小,但是通常仅为其它算法的一小部分:它不需要对被搜索的字符串中的字符进行逐一比较,而会跳过其中某些部分。通常搜索关键字越长,算法速度越快。它的效率来自于这样的事实:对于每一次失败的匹配尝试,算法都能够使用这些信息来排除尽可能多的无法匹配的位置。

    假设被检索文字列是“1234567890”,检索文字列是“MOORE”。简单的比较需要执行十次才得到结论不匹配。

    被检索文字列:1234567890
      第一次比较:M....         (M和1比较,不匹配)
      第二次比较: M....        (M和2比较,不匹配)
      第三次比较:  M....       (M和3比较,不匹配)
            ...
      第十次比较:         M....(M和0比较,不匹配)
    

    ※未参与比较的文字用【.】占位。

    BM算法只需要2次比较。

    被检索文字列:1234567890
      第一次比较:....E        (E和5比较,不匹配,并且5不是MOORE中任何文字)
      第二次比较:     ....E   (E和0比较,不匹配,并且0不是MOORE中任何文字)
    

    第一次从检索文字的末尾开始,因为如果被检索文字的第5文字位置不是E,则无论前4个文字是什么,都绝不可能匹配了。这一点比较容易理解。
    那么,为什么不用E和6比较呢?

    这是BM算法又一处精妙之处。在E和5进行比较的时候不仅知道他们不相等,而且还知道了5不和检索文字MOORE中的任何一个文字相等,这使得下面这些比较都可以省略掉。

    被检索文字列:....5......
    不需要的比较: ...R.       (E和5比较时也同时发现5不等于R,于是这个比较是不必要的)
    不需要的比较:  ..O..      (E和5比较时也同时发现5不等于O,于是这个比较是不必要的)
    不需要的比较:   .O...     (E和5比较时也同时发现5不等于O,于是这个比较是不必要的)
    不需要的比较:    M....    (E和5比较时也同时发现5不等于M,于是这个比较是不必要的)


    发明者论文:
    http://www.cs.utexas.edu/users/moore/publications/fstrpos.pdf
    http://www.cs.utexas.edu/~moore/best-ideas/string-searching/fstrpos-example.html


    BM算法是跳跃着前进的。

    第三步:BM过程展示

    BM算法实施方法是从后向前进行匹配。我们先来见证一下这种方法的威力。

     

    此处采用作者论文中的例子:

    从模式串最后一个字符开始匹配,发现F和T不匹配,除此之外,F在模式串AT-THAT中根本就不存在,这个意味着匹配的可能性为0.我们可以直接跳过前7个字符。



     我们只是添加了一个判断,效率瞬间提高很多。这个和BF、KMP有什么不同呢?这两种算法,目标串的指针i总是以一步一步的前进,而BM则并没有采用这种方式,它可以一下子增加7(本例),这就是跳跃式思维的表现形式,这个更接近人的思维方式。(下面会有更深入层次的分析前缀匹配和后缀的匹配差异)

    BM算法采用了两种启发性的规则:坏字符规则和好后缀规则,决定跳跃的距离。

    1) 坏字符规则(Bad Character)

      在BM算法从后向前扫描的过程中,若已经有m个字符匹配成功,第m+1个字符X(从后向前)匹配失败,则按下面两种情况讨论:

       a)如果字符x在模式P中没有出现,直接全部跳过该区域。

       b)如果字符x在模式P中出现,则以该字符进行对齐。

    我们其实已经见识过a)这个规则,就是上面的例子。

    2)好后缀规则(Good Suffix)

    在BM算法从后向前扫描的过程中,若已经有m个字符匹配成功,第m+1个字符X(从后向前)匹配失败,则按下面两种情况讨论:

     a) 如果已经匹配的m个字符,在模式串其他位置也出现过记为m’,则将m’和这m个字符对齐

    b) 如果a)中所说情况没有出现,此时需要检查模式串P,若P存在最长前缀同时也是P的后缀,则将sP对应的后缀对齐。

    上述两个好后缀规则中取最小的一个移动。

    其实,在好后缀规则中,如果第一条成立其实就不用检查第二条,因为第二条如果存在,移动距离肯定比第一条大。但是如果第一条不成立,意味着移动距离是模式串P的长度,此时需要检查第二条,如果第二条成立,则安全移动的距离便变小了。

    更多:

    http://wlh0706-163-com.iteye.com/blog/1847214

    http://dsqiu.iteye.com/blog/1700312

    http://wlh0706-163-com.iteye.com/blog/1847214

    http://blog.csdn.net/left_la/article/details/8881311

  • 相关阅读:
    解决RuntimeError: cuda runtime error (30) : unknown error at /pytorch/aten/src/THC/THCGeneral.cpp:70&NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver. Make sure that the late
    查看Ubuntu/Anaconda/cuda/cudnn/Tensorflow/Pytorch版本
    创建新用户
    142. Linked List Cycle II
    网页版Instagram如何发照片
    141. Linked List Cycle
    将博客搬至CSDN
    92. Reverse Linked List II
    Dlib使用过程全记录(一)
    定制new和delete
  • 原文地址:https://www.cnblogs.com/youxin/p/3301120.html
Copyright © 2011-2022 走看看