关于BM算法的一些思考

1. 什么是BM算法?

   见  A Fast String Searching Algorithm, with R.S. Boyer. Communications of the Association for Computing Machinery,

   是Boyer于1977年发表的一个算法,用于字符串匹配。

 

 

2. 与KMP算法相比?

  与经典的KMP算法相比,BM算法在很多情况下效率更高,它有两个特点:

  一是它在遍历正文时的平均比较次数与pattern的长度反比,这一点很历害。

  二是它在处理大字母表时候性能更佳。

  从表面上看KMP算法号称O(m+n)的时间复杂度,BM最坏为O(m*n),但实际效率反而是BM更高(见参考3),这是由于实际情况时经常能达到BM的平均效率。所以在内核的iptables匹配时,选择bm算法的时候居多!

 

3. 核心

 

   BM算法的核心是两个原则,这在下面的参考2中可以找到,具体原理它已经说的很清楚了。

  一。 坏字符原则

 

 

           i.  如果字符x在模式P中没有出现,那么从字符x开始的m个文本显然不可能与P匹配成功,直接全部跳过该区域即可。

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

 

 

  二。 好后缀原则

 

 

          i.  如果在P中位置t处已匹配部分P'在P中的某位置t'也出现,且位置t'的前一个字符与位置t的前一个字符不相同,则将P右移使t'对应t方才的所在的位置。

         ii. 如果在P中任何位置已匹配部分P'都没有再出现,则找到与P'的后缀P''相同的P的最长前缀x,向右移动P,使x对应方才P''后缀所在的位置。  

 

 

4. 个人的一点理解

 

  需要说明的是原则一是核心,原则二是对原则一的补充优化;换句话说,仅仅利用原则一就能在正文中完成匹配,但如果结合原则二可以很好地优化某些情况,从而提高效率!

 

  还有一点,如果只使用原则一,那么需要注意一个地方。BM算法的原论文里也忽视了这一点,比如下面这种情况:

 

  

 按原论文的意思,这个时候c与X(蓝绿色部分)产生了坏字符,于是根据坏字符原则,下一次对齐的地方是"patter中的最右边的X"与text中的当前坏字符X,    那么这就产生了回退--pattern相对于text向左移动。要消除这个bug,就要在应用原则一的时候判断,不能让pattern左移!即一旦出现图中这种情况:

       当前坏字符在pattern虽然有匹配,但由于匹配的位置在当前坏字符位置右边,于是相当于没有匹配,同样视为坏字符原则的第 i 种情况

 

之所以原论文会有这种疏忽,我觉得是因为原文的意思是在两个原则结合进行的前提下,上面提到的这种疏忽完全可以被原则二--好后缀原则会弥补这个bug ! 但严谨地讲来,这确实是一个不对的地方!

 

5.  SNORT2.7.0中BM算法的一点疑问

     在参考2中提到了SNORT2.7.0的算法,但个人觉得原文中的MakeSkip()函数有些问题:

    原文中的:

  

  应该改为:

 

   否则,在这面这种情况下,匹配虽然能成功,但会多匹配 一次,,,可能是作者一个小疏忽:

 

 

6.     最后附上自己修改过的源代码,同时还有一些自己测试用的打印代码,主要是为了观察方便

 

 

参考:

 

1. BM算法的原论文

   http://userweb.cs.utexas.edu/users/moore/publications/fstrpos.pdf

 

 

 

2.网上资料虽多,准确很少,这是个不错的原创:

   原理说明:

   http://www.javaeye.com/topic/352954

   算法的C代码(个人觉得有个疑点,在上面5中有说明):

   http://ouyangjia7.javaeye.com/blog/353137

 

 

 

 

3.关于BM算法的一点改进:

 

 

 

 

 

 

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值