Boyer Moore算法其实也是从上期的算法中得到了其实,但是这个算法的进步可要比之前的算法大的多。他会将需要查找的子字符串解析处理,将某个字符出现的最右侧的位置记录下来,然后如果我们匹配失败,就可以根据这个信息回退了。显然,如果我们已经匹配的字符串中如果没有重复的内容,那么从子字符串到匹配失败的位置都不会由符合子串的内容。我们的right数组只是考虑了有重复的情况而已。如果有和失败处的字符相同的,那我们就把他移动到与哪个字符相同的位置继续匹配就好了。
class boyermoore
{
private:
int r = 256;
std::string pat;
int right[256];
public:
boyermoore(std::string pat)
{
this->pat = pat;
int m = pat.length();
std::fill(right, right + r, -1); //不包含在模式字符串中的值设为-1
for (int i = 0; i < m; i++)
{
right[pat[i]] = i; //将包含在模式中的值设为他出现的最右边的位置
}
}
int search(std::string txt)
{
int n = txt.length();
int m = pat.length();
int skip;
for (int i = 0; i < n - m; i += skip)
{
skip = 0;
for (int j = m - 1; j >= 0; j--) //j代表已经匹配的字符的个数
{
if (pat[j] != txt[i + j])
{
skip = j - right[txt[i + j]];
if (skip < 1)
{
skip = 1;
}
break;
}
}
if (skip == 0) //找到匹配
return i;
}
return n; //未找到匹配
}
};
运行结果
看吧,这个算法比KMP算法,不仅好理解的多,更有更快的运行速度,并且占用更少的内存!这也侧面认证了算法的重要性。