BMH文本搜索算法

来源:互联网 发布:生死狙击桐哥刷枪软件 编辑:程序博客网 时间:2024/05/17 03:45

全称:Boyer-Moore-Horspool算法

实现从text中搜索pattern,返回其最小出现的位置;

算法思想:

1. 搜索文本时,从后到前搜索;

2. 如果碰到不匹配时,移动pattern,重新与text进行匹配;

关键:移动位置的计算shift_table如下图所示。

其中k为Pattern[0 ... m-2]中,使Pattern [ k ] ==Text [ i+m-1 ]的最大值;

                                                    如果没有可以匹配的字符,则使Pattern[ 0 ]==Text [  i+m ],即移动m个位置

3. 如果与Pattern完全匹配,返回在Text中对应的位置;

4. 如果搜索完Text仍然找不到完全匹配的位置,则返回-1,即查找失败

计算公式为:

如果在Pattern[0...m-2]中有Text[i+m-1]对应的字符c:shift[ (int)c ]=m-1-max{ 0 =< i < m-1 | p[i]=c }

如果在Pattern[0...m-2]中没有对应的字符c:shift[ (int)c ]=m


有匹配时的图:

性能分析:

Text对应长度为m,Pattern对应长度为n

时间复杂度:O(m*n);

空间复杂度:固定为256(ASCII中值的个数)

代码实现:

/*Data:2011.9.12  Middle Autumn Day*//*Authur: Bai YongHui*//*text: search in it; pattern: want to search*//*get the minial position whear pattern appears in text*/#include <stdio.h>#include <string.h>//计算shift表void getShiftTable(int table[], int num, char pattern[]){int len=strlen(pattern);int nArrayIter=0;for(; nArrayIter<num; nArrayIter++)table[nArrayIter]=len;int nCharIter=0;//注意这样循环的好处在于:如果有重复的字符,左边赋的shift值会被右边的相同字符的shift覆盖掉//从而保证正确性//a[0...len-2]for(; nCharIter<len-1; nCharIter++)table[(int)pattern[nCharIter]]=len-1-nCharIter;}//BMH Search算法int BMHSearch(char text[], char pattern[]){int nTextLen=strlen(text);int nPatternLen=strlen(pattern);int shiftTable[256]={0};getShiftTable(shiftTable, 256, pattern);int nTextPos=0;int nPatternPos;//text[nTextPos+nPatternLen-1...0]while(nTextPos+nPatternLen<nTextLen){//printf("%d\n", nTextPos);//每换到一个新的位置查找pattern,都需要重置nPatternPosnPatternPos=nPatternLen-1;//小循环,遍历pattern[nPatternLen-1...0]while(nPatternPos>=0){if(pattern[nPatternPos]==text[nTextPos+nPatternPos]){nPatternPos--;}else{nTextPos+=shiftTable[(int)text[nTextPos+nPatternLen-1]];break;}}if(nPatternPos<0)return nTextPos;}//search failedreturn -1;}void main(){char * text="detective";char * pattern="date";printf("%s\n%s\n", text, pattern);int firstPos=BMHSearch(text, pattern);if(firstPos==-1)printf("search failed\n");elseprintf("the first place where pattern appears is: %d\n", firstPos);}