全称: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,都需要重置nPatternPos nPatternPos=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 failed return -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"); else printf("the first place where pattern appears is: %d\n", firstPos); }