Boyer Moore 简易版算法

 Boyer Moore子字符串搜索算法是非常难的算法,但是它的简易版本却是不难的,而且搜索速度很快,下面就学习一下简易版吧。

 Boyer Moore是从子串的右到左搜索的,当然搜索主串文本的顺序还是从左到右的。虽然是简化版,但是速度也不比KMP差。

如下图:

Boyer Moore 简易版算法_第1张图片

如图比较到N的时候与E不匹配,那么我们就在子串里面NEEDLE看看有没有N这个字母,刚好是有的,所有就移到子串N的位置进行比较,那么一下子就跃进了很多了; 在看到了S的位置,不匹配,看看子串里面有没有S这个字母,没有,所以我们整个子串都右移,如此反复最后就找到匹配的了。只比较了4次失败的,加上最后一次成功的6个字母比较,才比较了10次。速度很快。

下面看看它和暴力法的对比程序: 

#include<iostream>
#include<vector>
#include<algorithm>
#include<string>

using namespace std;

class BoyerMoore
{
public:
	BoyerMoore(string pat);

	int search(string text);

private:
	vector<int> rightSkip;
	string pat;
};

BoyerMoore::BoyerMoore(string pa):pat(pa)
{
	rightSkip.resize(256, -1);
	int j = 0;
	for (auto s:pat)
		rightSkip[s] = j++;
}

int BoyerMoore::search(string text)
{
	int n = text.length();
	int m = pat.length();
	int skip = 0;
	//i定位开始比较位置,从i+m-1位置开始向前比较,每次不相等,i向前跃,j复位为m-1
	for (int i = 0; i <= n-m; i+=skip)
	{
		skip = 0;
		for (int j = m-1; j >= 0; j--)
		{
			if (pat[j] != text[i+j])
			{
				skip = j - rightSkip[text[i+j]];
				if(skip < 1) skip = 1;
				break;
			}
		}
		if(skip == 0) return i;
	}
	return n;
}

vector<int> bfSearch(string &text, string &substr)
{
	vector<int> begIndex;
	int n = text.size();
	int m = substr.size();

	//注意这里是i<=n-m不是i<n-m
	for (int i = 0; i <= n - m; i++)
	{
		int j = 0;
		for (; j < m; j++)
		{
			if (substr[j] != text[i+j])
			{
				break;
			}
		}
		if (j == m)
		{
			//注意这里是i,不是i-m
			begIndex.push_back(i);
		}
	}
	return begIndex;
}

int main()
{
	string substr1 = "abcadabcab";
	BoyerMoore bm(substr1);
	string str1 = "abcababcadcabcdceabcadabcabcadabcab";
	cout<<bm.search(str1)<<endl;

	vector<int> vibf = bfSearch(str1,substr1);

	for (int i = 0; i < vibf.size(); i++)
	{
		cout<<vibf[i]<<" ";
	}
	cout<<endl;

	system("pause");
	return 0;
}

 记录了出现子串的下标,初次出现的结果是一样的。暴力法记录了全部出现的初次下标。


 

 

 

 

你可能感兴趣的:(Moore,Boyer,简易算法)