• 字符串匹配之horspool算法(简化的BM算法)


        前面介绍在BF,KMP这些算法的时候老是提到BM这个东西,究竟这什么东西,有啥高深的,这些问题我们如今不去考虑。不知道,认真读前几篇文章的读者有没有发现前面的算法都是从模式串的前面開始匹配的,那我们就想能不能从模式串的后面開始匹配了? 答案肯定是能够的。所以这就有了我们今天的这篇文章Horspool算法,这个算法是基于字符串后缀的匹配算法。
    在上一篇文章中,我们学习了一个概念叫好字符(又叫好后缀),大家都知道有好必有坏吧,所以我们今天再来学习一个概念-----坏字符。

    一、坏字符与模式串滑动

        坏字符是串S中引起匹配失败的字符,坏字符又能够分为两类:
         1. 坏字符不在模式串T中,例如以下样例

           S: "abbadcababacab", T: "babac", 串S中的字符d就是一个坏字符

        

        对于这样的情况,我们直接把模式串向后移动使其T[0]与d的下一位对其,然后从后開始进行下一轮匹配;
        2. 坏字符串在模式串中,如上面样例移动后,从后往前比較,b和c不同样,而字符b在模式串T中出现,此时就把模式串移动到模式串的该字符和串的该坏字符对其,可是假设该坏字符在模式串种出现了不止一次,我们怎么移动了?这时候,为了保守起见,我们移动模式串使模式串种最右端的坏字符和串的该坏字符对其,例如以下:
        

        假设依照最以下的方法移动,和最左端的字符对其,则可能会漏掉匹配项,如上图所看到的。

    二、知道了坏字符和怎样滑动模式串了,计算移动步伐step
        代码的难处在遇到坏字符后该怎样移动模式串,即计算移动步伐(step)。
        1. 对于第一种情况,坏字符不在模式串中,直接就T[0]移动到该位置之后,
        

          j=3时发生了不匹配,此时移动步伐(step)=j+1=4.
        2. 对于另外一种情况,坏字符在模式串中,为了得到该字符在模式串中的最右位置,须要有一个表记录坏字符在模式串中的最右位置,设其为table[i], 则步伐step= j-table['e'].

    三、实现
         //update 2014-06-07
         int horspool(const char *S, const char *T){
              if(S==NULL || T==NULL) return -1;
              int n = strlen(S);
              int m = strlen(T);
              int table[256] = {-1};
              //记录模式串中字符出现的最右位置
              for(int i=0; i<m; ++i)
                   table[ T[i] ] = i;
              //移动步伐
              int step = 0;
              for(int i=0; i+m<=n; i+=step){
                   step = 0;
                   //開始匹配,从右往左匹配
                   for( int j=m-1; j>=0; --j){
                        if( S[i+j] != T[j] ){
                             step = j-table[ S[i+j] ];
                             //防止原地踏步
                             if(step <1 )  step = 1;
                             //本轮匹配失败,从新位置開始比較
                             break;
                        }
                   }
                   //一轮匹配结束后,没有匹配失败的,说明匹配成功
                   if(step == 0)  return i;
              }
              return -1;  //匹配失败
         }
    

    四、写在后面的话
    字符串匹配这个系列,加上这篇已经写的有4篇文章了,这个系列还剩最后一个算法没有写,有时间了把最后一个算法补上后就这个系列就算是Over了。

    假设你认为本篇对你有收获,请帮顶。
    另外,我开通了微信公众号--分享技术之美,我会不定期的分享一些我学习的东西.
    你能够搜索公众号:swalge 或者扫描下方二维码关注我

    (转载文章请注明出处: http://blog.csdn.net/swagle/article/details/24269403 )


  • 相关阅读:
    for循环中变量的作用域问题
    一个数与0进行按位或,能取整
    Spring中日志的使用(log4j)
    MyBatis实现动态语句操作
    MyBatis实现简单增删改查操作
    python计算2的平方根,并输出小数点后的第100万位数字
    Spring配置文件报错:Multiple annotations found at this line: - Element type "beans" must be followed by either attribute specifications, ">" or "/>". - Start tag of element <beans>
    python跳出多重循环
    python中的生成器(二)
    python中的生成器(一)
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/4059444.html
Copyright © 2020-2023  润新知