BM算法

本文介绍BM算法的工作原理及其实现细节,BM算法是一种高效的字符串匹配算法,其效率远超KMP算法。文章深入解析了BM算法中的坏字符规则与好后缀规则,并通过实例演示了如何利用这两种规则进行字符串匹配。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

BM算法的效率是KMP算法的3-5倍,是一种效率高,构思巧妙的字符串匹配算法。

与基于前缀比较的暴力匹配算法以及KMP算法不同,BM算法采用基于后缀的比较方法,在BM算法中,包含了两个并行的比较方法:1.坏字符算法;2.好后缀算法。算法的核心在于,通过并行的坏字符与好后缀算法,计算出每次后移的最大位移(不超过模式串本身大小)。

算法的开始将待匹配字符串(textString)与模式串(patString)从头部进行对齐。自尾部开始进行字符比较,若尾部比较失败,则可通过一次比较确定匹配失败,进行位移操作。


如图,当模式串的E与A进行比较失败时,即可确定此次匹配失败,进入移位操作,通过坏字符算法与好后缀算法分别获取位移值,取两者中的最大值进行位移操作。下面,将详细对这两个算法进行分析。

坏字符算法:

当待匹配串中的当前字符与模式串中对应位置的字符串不一致时,当前字符即为坏字符,此时存在两种情况:1.坏字符不存在于模式串中;2.坏字符在模式串中存在,且最近一次出现位置为lastpostion(注:本文均采用数组记数方式,从0开始);

依据公式: 位移数(Shift) = 坏字符在当前匹配串中的位置(position) - lastposition;

第一种情况下,坏字符不存在于模式串中,则记lastposition为-1,此时位移数即为当前的position + 1,亦即将整个patString移至当前坏字符的下一位进行匹配:


此时状态如上图所示,依然进行尾部匹配,此时为第二种情况,坏字符P存在于模式串中,position为6(与当前patString中匹配字符的位置对应),lastposition为4,则

Shift = 6 - 4 = 2;

此时状态如下:


在接下来的匹配过程中,E,LE,PLE,MPLE这类尾部匹配的字符串均为好后缀(Good suffix).

好后缀算法:

Shift = 好后缀的位置 - 该后缀在搜索词中上一次出现的位置(last_position)

在比较时,由于算法本身采用后缀比较法,采用好后缀的最后字符的位置作为标记位置,则下一步状态如图:


Shift = postion of E(6) - last position of E(0) = 6;

到这里整个算法流程已经比较明确了,经过重复,后面的结果如下:

继续比较,发现坏字符P,按照公式进行移位:

Shift = 6 - 4 = 2;


自尾部比较,发现匹配,则返回结果,如当前搜索串在textString中的位置,进行标记,算法分析部分至此结束,代码部分如下,仅供参考,欢迎批评指正。


#include "Algobm.h"

int checkSuffix(std::string patString, char char_sfx,int lastPosition)
{
	int position = -1;
	int size = patString.length();	
	
	for(int i = size - 1; i > -1; --i)
	{
		if(patString.at(i) == char_sfx)
		{
			position = i;
			break;
		}
	}
	
	return lastPosition - position;
}

int BoyerMoore(std::string textString, std::string patString)
{
	int notFound = -1;
	int textSize = textString.length();
	int patSize = patString.length();
	int curPos = patSize - 1;
	while (curPos <= textSize)
	{
		int curPosTmp = curPos;
		for(int pos = patSize - 1; pos > -1; --pos,--curPosTmp)
		{
			if(textString[curPosTmp] == patString[pos])			
			{
				if(pos == 0)
					return curPosTmp;
				continue;
			}
			else
			{
				curPos += checkSuffix(patString, textString.at(curPosTmp),pos);
				break;
			}
		}
	}
	
	return notFound;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值