4.4模式匹配-BM算法


4.4模式匹配-BM算法

类似于KMP算法,遵从“坏字符、好后缀”规则。

(1)BM算法来历

1977年,德克萨斯大学的Robert S. Boyer教授和J Strother Moore教授发明了一种新的字符串匹配算法:Boyer-Moore算法,简称BM算法。该算法从模式串的尾部开始匹配,且拥有在最坏情况下O(N)的时间复杂度。在实践中,比KMP算法的实际效能高。

(2)BM算法

int BM(char *x, char *y)
{
	int m;//模式串的长度
	int n;//目标串的长度
 
	int i;//模式串中匹配的位置
	int j;//目标串中匹配的位置

	int bmGs[XSIZE];//好后缀表 
	int bmBc[ASIZE];//坏字符表
 
	preBmBc(x, bmBc);
	preBmGs(x, bmGs);

	m = strlen(x);
	n = strlen(y);

	j=0;
	while (j < n-m )
	{
		for (i = m - 1; i >= 0 && x[i] == y[i + j]; --i);

		if (i < 0)
		{
			return j;
		}
		else
		{
			j += (bmGs[i]) > (bmBc[y[i+j]] -m + 1 +i) ? (bmGs[i]) : (bmBc[y[i+j]] -m + 1 +i);
		}
	}
	if (j >= n-m)
	{
		return -1;
	}
}
(3)模式匹配

# include <stdio.h>
# include <stdlib.h>
# include <string.h>

#define XSIZE 8
#define ASIZE 256

void preBmBc(char *x, int bmBc[]);
void preBmGs(char *x, int bmGs[]);
void suffixes(char *x, int *suff);
int BM(char *x, char *y);

void main()
{
	char x[100];
	char y[100];
	int location;

	printf("input string patter:\n");
	gets(y); gets(x);

	location = BM(x, y);
 
	printf("\n模式串在目标串中出现的位置是:%d\n",location+1);
}

int BM(char *x, char *y)
{
	int m;//模式串的长度
	int n;//目标串的长度
 
	int i;//模式串中匹配的位置
	int j;//目标串中匹配的位置

	int bmGs[XSIZE];//好后缀表 
	int bmBc[ASIZE];//坏字符表
 
	preBmBc(x, bmBc);
	preBmGs(x, bmGs);

	m = strlen(x);
	n = strlen(y);

	j=0;
	while (j < n-m )
	{
		for (i = m - 1; i >= 0 && x[i] == y[i + j]; --i);

		if (i < 0)
		{
			return j;
		}
		else
		{
			j += (bmGs[i]) > (bmBc[y[i+j]] -m + 1 +i) ? (bmGs[i]) : (bmBc[y[i+j]] -m + 1 +i);
		}
	}
	if (j >= n-m)
	{
		return -1;
	}
}

void preBmBc(char *x, int bmBc[])
{
	int m;
	int i;

	m = strlen(x);
	for (i = 0; i < ASIZE; i++)
	{
		bmBc[i]=m;
	}

	for (i = 0; i < m - 1; i++)
	{
		bmBc[x[i]] = m-1-i;
	}
}

void suffixes(char *x, int *suff)
{
 int i;
 int f;
 int g;
 int m;

 m = strlen(x);
	f = 0;
	suff[m-1] = m;
	g = m - 1;
	for (i = m - 2; i >= 0; --i)
	{
		if (i > g && suff[(m-1)-(f-i)] < i - g)
		{
			suff[i] = suff[(m-1)-(f-i)];
		}
		else
		{
			if (i < g)
				g=i;
			f=i;
			while (g >= 0 && x[g] == x[g + m - 1 -f])
			{
				g--;
			}
			suff[i] = f - g;
		}
	}
 
	for (i = 0; i < m; i++)
	{
		printf("%d ",suff[i]);
	}
	printf("\n");
}

void preBmGs(char *x, int bmGs[])
{
 int i;
 int j;
 int suff[XSIZE];
 int m;
  
 m=strlen(x);
	suffixes(x, suff);

	for (i = 0; i < m; ++i)
	{
	bmGs[i] = m;
	}

	j = 0;

	for (i = m-1;i >= 0; --i)
	{
		if (suff[i] == i+1)
		{
			for (; j < m - 1 - i; ++j)
			{
				if (bmGs[j] == m)
				{
					bmGs[j] = m - 1 - i;
				}
			}
		}
	}
 
	for (i = 0; i <= m-2; ++i)
	{
		bmGs[m - 1 -suff[i]]= m - 1 - i;
	}
	for (i = 0; i < m; i++)
	{
		printf("%d ",bmGs[i]);
	}
	printf("\n");
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值