您的位置:首页 > 其它

对于BMH算法的理解——文本匹配算法

2015-06-04 11:20 393 查看
之前的BM算法已经剔除了大部分的冗余遍历,使得整个的模板匹配算法变得更加高效,但是很明显从例子上就可以看出,有两个缺点一是跨度的时机不能很好的把握,而是仍然有冗余遍历。所以BMH算法被提出来作为BM算法的改进算法。

BMH算法全称是Boyer-Moore-Horspool算法。它不再像BM算法一样关注失配的字符,它的关注的焦点在于匹配文本每一次匹配失败的最后一个字符X,根据这个字符X是否在模板出现过来决定跳跃的步数,否则跳跃模板的长度。



所以分了两种情况:

一:字符X不在模板P中,则跳跃的步数为模板P的长度

二:字符X在模板P中,跳跃的步数为字符X距离离尾部最近的字符X的距离(不包括最后一个字符)



加入文本为missipipi,模板为pip:



只要三次匹配即可。

BMH算法源代码如下(C++版):

#include <iostream>
#include <string.h>

using namespace std;

///计算模板一般情况下的滑动窗口
void getShiftFrame(int* table, int len,  string needle)
{
int i = 0;
//存储字符距离最右端的距离,重复字符只存最右端距离
for(; i < len; i++)
table[needle[i]] = i;
}

//计算模板应该滑动的距离
int Dist_BMH(char target, int* table, int len){
//如果模板存在目标字符,则返回与右端的距离作为滑动距离
if(table[target] > -1)
return len - table[target] - 1;
//如果模板不存在目标字符,则使模板的开始指向目标字符的下一位
else
return len;
}

//BMH Search算法
int BMHSearch(string haystack,string needle)
{
int n = haystack.size() - 1;//haystack长度
int m = needle.size() - 1;//needle长度
if(m == -1) return 0;
if(m > n) return -1;
int i = m, k = m, q = m;//i是haystack的指针,k是needle的指针,q是记录现在滑动的点,也就是needle滑动到haystack的位置
int* table = new int[256];//创建一个保存滑动距离的窗口
for(i = 0; i < 256; i++)
table[i] = -1;
i = m;
getShiftFrame(table, m,needle);//计算模板一般情况下的滑动窗口
while(i <= n){
//从后往前匹配,若成功则返回下标,否则取得滑动距离,使模板滑动到对应的位置
if(haystack[i] == needle[k])
{
if(k == 0)
return i;
else{
k--;
i--;
}
}else{
i = q + Dist_BMH(haystack[q], table, m + 1);
q = i;
k = m;
}
}
return -1;
}

int main()
{
string haystack = "abbc";
string needle = "bc";
int firstPos = BMHSearch(haystack, needle);
if(firstPos < 0)
cout<<"search failed\n"<<endl;
else
cout<<"first appeared place:"<<firstPos<<endl;
return 0;
}
参考文章:《基于BM算法的分布式入侵系统检测系统的研究》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: