BM算法实现

main文件:

#include "BM.h"

//BF算法(朴素模式匹配算法):时间复杂度O(strlen(src)*strlen(dest)), 空间复杂度O(1)
//KMP:时间复杂度O(strlen(src)+strlen(dest)), 空间复杂度O(strlen(dest))
//BM :时间复杂度最好O(strlen(src)/strlen(dest)), 最坏O(strlen(src)*strlen(dest)), 空间复杂度:建表占用空间 

int main()
{
	char *src =  "bbbbshfdsdhfhsadfsdahghfsadfsahdfsbdfsdfsdfsdsdfsdfsdaf";
	char *dest = "bdfsdfsdfsd";//bdfsdfsdfsd

	printf("src  = %s\n", src);
	printf("dest = %s\n", dest);

	//-----------test bad_char---------------//
	//int loc = match_by_bad_char(src, dest);		//最坏自符表
	//printf("loc = %d\n", loc);

	//-----------test good suffix------------//
	//int loc = mathc_by_good_suffix(src, dest);//最好后缀表	
	//printf("loc = %d\n", loc);

	//-----------test BM---------------------//
	int loc = match_by_BM(src, dest);
	printf("\n\nthe match loc = %d\n", loc);

	system("pause");
	return 0;
}

BM.h文件

#pragma once

#include <cstdio>
#include <cstdlib>
#include <cstring>

void build_bad_char_shift(const char *str, int *shift);
void bulid_good_suffix_shift(char *str, int *shift);
int match_by_bad_char(const char *src, const char *dest);
int mathc_by_good_suffix(const char *src, char *dest);
int match_by_BM(char *src, char *dest);

/***********************************************************************/
//FUNCTION:建立坏字符表
void build_bad_char_shift(const char *str, int *shift)
{
	int len = strlen(str);
	for (int i = 0; i < 256; i++)
		shift[i] = len;

	for (int j = len-1; j >=0; j--)
		shift[(unsigned char)*str++] = j;
}

/***********************************************************************/
//FUNCTION:应用坏字符表匹配模式串
int match_by_bad_char(const char *src, const char *dest)
{
	int len_src = strlen(src);
	int len_dest = strlen(dest);

	if (len_dest > len_src)
		return -1;

	int *shift = (int *)malloc(sizeof(int)*256);
	build_bad_char_shift(dest, shift);

	int tride = len_dest;
	int s_id = len_dest;
	while (s_id <= len_src)
	{
		int d_id = len_dest;
		while (src[--s_id] == dest[--d_id])
		{
			if (d_id == 0)
				return s_id;
		}

		tride = shift[(unsigned char)src[s_id]];
		printf("s_id = %d\n", s_id);
		s_id += (tride > len_dest-d_id ? tride : len_dest-d_id) + 1;
		printf("s_id = %d\n", s_id);
	}

	free(shift);
	shift = NULL;

	return -1;
}

/***********************************************************************/
//FUNCTION:建立最好后缀字符表
void bulid_good_suffix_shift(char *str, int *shift)							
{
	int len = strlen(str);
	shift[len-1] = 1;
	char *p_now = str+len-2;
	char *p_prev, *p_next, *p_temp;
	char ch = str[len-1];
	int delta_len;					//应该移动的字符数

	for (int i = len-2; i >= 0; i--, p_now--)
	{	
		p_temp = str+len-2;

		while (true)
		{
			while (p_temp >= str && *p_temp-- != ch);
			p_prev = p_temp;
			p_next = str+len-2;

			if (p_prev < str && *(p_temp+1) != ch)		//寻找子串失败
			{
				delta_len = len;
				break;
			}

			bool match_flag = true;
			while (p_prev >= str && p_next > p_now)
			{
				if (*p_prev-- != *p_next--)
				{
					match_flag = false;
					break;
				}
			}

			if (!match_flag)		//继续往前寻找
				continue;
			else 
			{
				if (p_prev < str || *p_prev != *p_next)
				{
					delta_len = p_next - p_prev;
					break;
				}
			}

		}//while

		shift[i] = len-i + delta_len - 1;
	}//for

}

/***********************************************************************/
//FUNCTION::应用好后缀表匹配模式串
int mathc_by_good_suffix(char *src, char *dest)
{
	int len_src = strlen(src);
	int len_dest = strlen(dest);

	if (len_dest > len_src)
		return -1;

	int *shift = (int *)malloc(sizeof(int)*len_dest);
	bulid_good_suffix_shift(dest, shift);

	for (int s = 0; s < len_dest; s++)
		printf("shift[%d] = %d\n", s, shift[s]);

	int s_id = len_dest;
	while (s_id <= len_src)
	{
		int d_id = len_dest;
		while (src[--s_id] == dest[--d_id])
		{
			if (d_id == 0)
				return s_id;
		}

		s_id += shift[d_id] + 1;
	}

	free(shift);
	shift = NULL;

	return -1;
}

/***********************************************************************/
//FUNCTION:
int match_by_BM(char *src, char *dest)
{
	int len_src = strlen(src);
	int len_dest = strlen(dest);

	if (len_dest > len_src)
		return -1;

	int *shift_bad_char = (int *)malloc(sizeof(int)*256);
	build_bad_char_shift(dest, shift_bad_char);

	int *shift_good_suffix = (int *)malloc(sizeof(int)*len_dest);
	bulid_good_suffix_shift(dest, shift_good_suffix);

	printf("\nthe shift_bad_char array : \n");
	for (int s = 0 ; s < len_dest; s++)
		printf("s[%d] = %d\t", s, shift_bad_char[(unsigned char)dest[s]]);

	printf("\n\nthe shift_good_suffix array : \n");
	for (int s = 0; s < len_dest; s++)
		printf("s[%d] = %d\t", s, shift_good_suffix[s]);

	int s_id = len_dest-1;
	while (s_id <= len_src)
	{
		int d_id = len_dest-1;
		while (d_id > 0 && src[s_id] == dest[d_id])
		{
			s_id--;
			d_id--;
		}
		if (d_id == 0)
			return s_id;

		int tride_bad_char = shift_bad_char[(unsigned char)dest[d_id]];
		int tride_good_suffix = shift_good_suffix[d_id];
		s_id += tride_bad_char > tride_good_suffix ? tride_bad_char : tride_good_suffix;
	}

	free(shift_bad_char);
	shift_bad_char = NULL;
	free(shift_good_suffix);
	shift_good_suffix = NULL;

	return -1;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值