深入理解BM算法(附上C++代码)

BM算法
BM算法的一个特点是当不匹配的时候一次性可以跳过不止一个字符。即它不需要被搜索的字符串中的字符进行逐一比较,而会跳过其中的某些部分。通常搜索的关键字越长,算法速度越快。它的效率来源:对每一次失败的匹配尝试,算法都能够使用这些信息来排除尽可能多的无法匹配位置。它充分的利用待搜索字符串的一些特征,加快了搜索的步骤。
基于以下两个规则让模式每次向右移动的尽可能大的距离:
坏字符规则:当文本字符串中的某个字符跟模式串的某个字符不匹配时,我们称文本串中的这个失配字符为坏字符,此时模式串需要向右移动,移动的位数=坏字符在模式串中的位置-坏字符在模式串中的最右出现的位置。如果“坏字符”不包含在模式串之中,则最右出现的位置-1.坏字符针对的是文本串。
在这里插入图片描述

好后缀规则:当字符失配时,后位移数=好后缀在模式串中的位置-好后缀在模式串上一次出现的位置,且如果好后缀在模式串中没有再次出现,则为-1.好后缀针对的是模式串。

坏字符出现的时候有两种情况:
1.模式串中没有出现了文本串中的那个坏字符,将模式串直接整体对齐到这个字符的后方,继续比较。
在这里插入图片描述
在这里插入图片描述

2.模式串中有对应的坏字符时,让模式串中最靠右的对应字符与坏字符相对。(最靠右)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

好后缀规则:

1.如果模式串中存在已经匹配成功的好后缀,则把目标串与好后缀对齐,然后从模式串的最尾元素开始往前匹配。
在这里插入图片描述
在这里插入图片描述

2.如果无法找到匹配好的后缀,找一个匹配的最长的前缀,让目标串与最长的前缀对齐(如果这个前缀存在的话)。模式串【m-s,m】=模式串【0,s】
在这里插入图片描述

3.如果完全不存在和好后缀匹配的子串,则右移整个模式串。
贴上代码:

#include<iostream>
#define MAX 200
using namespace std;
void get_dist(int* dist, char* t, const int lenT)
{
    
    
	int i;
	for (i = 0; i <= MAX; i++)
		dist[i] = lenT;
	for (i = 0; i < lenT; i++)
		dist[(int)t[i]] = lenT - i - 1;
}
int BM(char* s, char* t, int* dist, const int lenS, const int lenT)
{
    
    
	int i, j, k;
	i = lenT - 1;
	while (i < lenS)
	{
    
    
		j = lenT - 1;
		k = i;
		while (j >= 0 && s[k] == t[j])
		{
    
    
			j--;
			k--;
		}
		if (j < 0)
			return i + 2 - lenT;
		else
			i = i + dist[s[k]];
	}
	if (i >= lenS)
		return 0;
}
int main()
{
    
    
	int cases;
	char s[MAX], t[MAX];
	int dist[MAX];
	cout << "请输入案例的个数:";
	cin >> cases;
	while (cases--)
	{
    
    
		cout << "请输入主串:" << endl;
		cin >> s;
		int lenS = strlen(s);
		while (1)
		{
    
    
			cout << "请输入需要匹配的模式串(以0结束):" << endl;
			cin >> t;
			if (!strcmp(t, "0"))
				break;
			int lenT = strlen(t);
			get_dist(dist, t, lenT);
			int pos = BM(s, t, dist, lenS, lenT);
			if (pos == 0)
				cout << "没有匹配项!" << endl;
			else
				cout << "匹配的开始位置为:" << pos << endl;
		}
	}
	system("pause");
	return 0;
}


本文参考:

https://mp.weixin.qq.com/s?__biz=MzUyNjQxNjYyMg==&mid=2247486150&idx=1&sn=9e9f8c35805c66132005cb634ef18171&chksm=fa0e6547cd79ec51529d0510f18161b65e54826231fae025d2cfbbd4f8a9656460f5b2d424b3&scene=21#wechat_redirect

猜你喜欢

转载自blog.csdn.net/qq_52269550/article/details/121343542