首页 > 其他 > 详细

字符串匹配算法——BM算法

时间:2014-03-14 00:43:20      阅读:509      评论:0      收藏:0      [点我收藏+]

BM算法是对KMP算法的一种改进 , 它的效率比KMP算法快3~5倍


BM算法主要根据两个原则: 1、坏字符   ,   2、好后缀。


假设存在主串S  , 长度为s_l, 模式串T中 , 长度为t_l

1、坏字符


如果在主串S中存在一个字符 , 并且这个字符在模式串T中不存在 , 那么模式串向右移t_l位。 (因为,如果这样的字符存在 , 那么在第一次匹配的时候 , 就能发现 , 所以需要向右移动 t_l 位的距离)


如果在主串S中存在一个字符 , 但这个字符不在模式串T中当前的位置 , 那么可以移动模式串 , 使得模式串T中最右边的该字符 , 与主串S对齐


因此:


                               t_l                x != T[ j ] ,    1 <= j  <= t_l  即模式串中不存在该字符

deltal ( x )  = 

                               m - max( k  /  T[ k ] = x ,  1 <= k < m) ,  x 在模式中最右边的位置



代码:

void bminitocc()//判断坏字符函数
{
	int i;
	for(i = 0; i < t_length; i++)
		occ[t[i]] = i;
}



2、 好后缀


有时坏字符启发会失败 。  把模式符号的最右匹配对齐到主串相应字符 , 将可能导致负移位。  但是移动一个位置是可行的,  但在这种情况下 , 从模式串的结构推导出最大可能的可移位距离将是更好的 , 这就叫好后缀启发。


好后缀有两种情况:

1、

  bubuko.com,布布扣

T中间的某一子串与已比较的的部分相等。


2、

bubuko.com,布布扣

T已比较部分的后缀和T的前缀相同


对于上面两种情况 , 我们取移位距离最小的 , 为将要移动的距离  ,  因为我们要保证存在的每一种可能都经过比较。


问题一: 现在 , 我们来看一种问题 , 当在某一次的比较时 , 该比较部分 , 即存在部分相同前缀 ,并且在T另一位置中又存在完全相同的一部分 , 这个时候我们可以发现 , 第一种情况(也就是T中间的某一子串与已比较的的部分相等)的移位距离更短 。  因此我们可以判断 , 只要两种情况都存在时,我们只需要取第一种情况的距离就行了 , 因为这相对于第二种情况肯定是更短的。


问题二: 当我们知道了模式串开头处的好后缀 , 那么我们就能知道什么时候有第二种情况出现


根据上面的两种情况 , 我们只需要求出第一种情况 , 我们就能知道第二种情况



代码:

f []  存储每个位置的好后缀

next []  存储最终应该的移位距离

void bmpreprocess1()//存储存在的所有好后缀的位置
{
	int i = t_length , j = t_length+1;
	f[i] = j;

	while(i >= 0)
	{

		while(j <= t_length && t[i-1] != t[j-1])
		{
			if(next[j] == -1)  next[j] = j-i;  //当存在好后缀的时  , 应该右移的位置
			j = f[j];
			
		}

		i--;
		j--;
		f[i] = j;
	}
	//cout<<f[0]<<endl;
}

void bmpreprocess2()//计算 , 当好后缀存在时 , 应该向右移动的距离
{
	int i , j;
	j = f[0];
	for(i = 0; i < t_length; i++)
	{
		if(next[i] < 0)  next[i] = j;//当只有一部分匹配后缀在模式开始处出现时。
		if(i == j) j = f[i];
		printf("%dc   %d\n" , next[i] , f[i]);
	}
}







字符串匹配算法——BM算法,布布扣,bubuko.com

字符串匹配算法——BM算法

原文:http://blog.csdn.net/zengchen__acmer/article/details/21186595

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!