现在的位置: 首页 > 综合 > 正文

单模式字符串匹配算法—Tuned Boyer-Moore algorithm实现

2018年04月22日 ⁄ 综合 ⁄ 共 2654字 ⁄ 字号 评论关闭

 http://hi.baidu.com/kmj0217/blog/item/5569eb7b1f659dfd0bd18710.html

算法介绍及伪代码查看:http://www-igm.univ-mlv.fr/~lecroq/string/tunedbm.html

The function preBmBc is given chapter Boyer-Moore algorithm.

void TUNEDBM(char *x, int m, char *y, int n) {
   int j, k, shift, bmBc[ASIZE];
 
   /* Preprocessing */
   preBmBc(x, m, bmBc);
   shift = bmBc[x[m - 1]];
   bmBc[x[m - 1]] = 0;
   memset(y + n, x[m - 1], m);
 
   /* Searching */
   j = 0;
   while (j < n) {
      k = bmBc[y[j + m -1]];
      while (k !=  0) {
         j += k; k = bmBc[y[j + m -1]];
         j += k; k = bmBc[y[j + m -1]];
         j += k; k = bmBc[y[j + m -1]];
      }
      if (memcmp(x, y + j, m - 1) == 0 && j < n)
         OUTPUT(j);
      j += shift;                          /* shift */
   }
}
/******************************************华丽的分割线*****************************/
 

根据上面伪代码 我的实现:

/*
Tuned Boyer-Moore algorithm
单模式匹配算法中最快的一种匹配算法,在BM算法之上进行了改进
主要思想就是:因为匹配时最耗时的就是检查模式串的字符跟主串的字符是否匹配,因此减少字符匹配的次数是这个算法的主要思想

在实际比较字符之前,进行多次滑动,同样运用“坏字符”规则,这里的预处理与Sunday算法有点区别,

遇到不匹配的字符的时候,检查模式子串最后一个字符在主串中的位置

然后比较是否相同,不同的话就移动模式串中最后一个字符 所需滑动的距离 继续寻找它在主串的位置.
*/
#include<iostream>
#include<string.h>
#include<malloc.h>
using namespace std;

#define MAX_SIZE 256

//预处理 得出字符的步长
int * preProcess(char * subStr)
{
    int subStrLen=strlen(subStr);
   
    int *charStep = new int[MAX_SIZE];//保存步长
   
    /*下面两句与Sunday算法有点区别,对比即可*/
    for(int i=0;i<MAX_SIZE;i++)
    {
            charStep[i]=subStrLen;       
    }
   
    for(int i=0;i<subStrLen-1;i++)
    {
            charStep[(unsigned char)subStr[i]]=subStrLen-1-i;       
    }  
    return charStep;
}

//匹配 找到后返回在主串中的偏移量 ,找不到返回-1
int TunedBM(char * mainStr,char *subStr)
{
    int mainStrLen=strlen(mainStr);
    int subStrLen=strlen(subStr);
    //预处理数组
    int *charStep=preProcess(subStr);
    int shift=charStep[(unsigned char)subStr[subStrLen-1]];//保存最后一个字符对应的偏移量

    charStep[(unsigned char)subStr[subStrLen-1]]=0;//置零 便于在主串中找到

    //扩大主串空间使得模式子串最后一个字符在主串后面连续出现子串长度次数
    char *newbase=new char[mainStrLen+subStrLen];
    memcpy(newbase,mainStr,mainStrLen*sizeof(char));
    delete[] mainStr;
    mainStr=newbase;
    newbase=0;
    memset(mainStr+mainStrLen,subStr[subStrLen-1],subStrLen);

    //开始查找
    int main_j=0;
    while(main_j < mainStrLen)
    {
                 int k=charStep[(unsigned char)mainStr[main_j+subStrLen-1]];
                 //在主串中寻找子串中最后一个字符位置
                 while(k !=0 )
                 {
                   main_j+=k; k=charStep[(unsigned char)mainStr[main_j+subStrLen-1]];
                   main_j+=k; k=charStep[(unsigned char)mainStr[main_j+subStrLen-1]];
                   main_j+=k; k=charStep[(unsigned char)mainStr[main_j+subStrLen-1]];       
                 }            
                 if(memcmp(subStr,mainStr+main_j,subStrLen-1) == 0 && main_j<mainStrLen)
                               return main_j;
                 main_j+=shift;
    }
    return -1;
}

int main()
{
char *mainStr="aabdasfasdfadf kmj asdfasdfasfaskmj";
char *subStr="kmj";
cout<<"子串位置为:"<<TunedBM(mainStr,subStr)<<endl;
getchar();
return 0;   
}

抱歉!评论已关闭.