BF算法与KMP算法

两个字符串匹配,匹配成功时,i和j同时后移一位。直至子串匹配完(即j>lensub)

而BF算法和KMP不同之处在于:

  • BF算法,当匹配失败时,j直接回到0位置,i回到上次的位置加一(即i-j+1)。这样前面匹配过的又要重新来一遍,浪费了好多时间
  • KMP算法,在匹配失败的时候,i不动,j回到他next数组对应的下标位。
//BF
int BF(char *s,char *sub,int pos)
{
	int i = pos;//主串
	int j = 0;//子串
	int lens = strlen(s);
	int lensub = strlen(sub);

	while(i < lens && j < lensub)
	{
		if(s[i] == sub[j])
		{
			i++;
			j++;
		}
		else
		{
			i = i-j+1;
			j = 0;
		}
	}
	if( j >= lensub)
	{
		return i-j;
	}
	else
	{
		return -1;
	}
}

KMP算法,首先要创建一个next数组来保存对应的next值

  • next数组保存的值,即匹配成功的子串长度(除了第一位是-1)

  • 需要比较的则是该字符串i-1位置和k位置的值是否相等。比如现在所在位置,i与k还是匹配失败,则k回到-1位置,因为不存在-1位置,说明主串i之前的匹配完了,还是失败。此时,需要i往前走一步,继续匹配。
//next数组的建立
void GetNext(int *next, char *sub)
{
	int lensub = strlen(sub);
	next[0] = -1;
	next[1] = 0;
	int k = 0;//前一项(也表示匹配到的真子串的长度)
	int i = 2;//后一项
	while (i < lensub)
	{
		if (k == -1 || sub[k] == sub[i - 1])//k==-1即主串与子串的第一位都不相等  或匹配成功
		{
			next[i] = k + 1;//next数组其实存放的是匹配成功的子串长度    如果匹配成功了,长度加一,即next++
			i++;
			k++;
		}
		else
		{
			k = next[k];//k回到next[k]的位置,再进行比较。如果一直不相等,最后k==-1,进入上面的语句
		}
	}
}

手动推导next数组和nextval数组

  • next数组各位的值,是从主串第一位开始,各位的前一位结束所寻找到的真子串的长度。(除了第一位是-1。第二位是0      固定的)
  • nextval数组是根据next数组计算的。比如i和j位置。先寻找next数对应下标的值,i位置的两个都是a,相等,所以nextval的值就等于next数组0下标处的值。
  • J位置的两个不相等,所以nextval值等于此位置next的值

next数组建立好了,根据next数组进行kmp的匹配

int KMP(char *s, char *sub, int pos)
{
	int i = pos; int j = 0;
	int lens = strlen(s);
	int lensub = strlen(sub);
	int *next = (int *)malloc(sizeof(int)*lensub);
	assert(next, sub);
	GetNext(next, sub);

	while (i < lens&&j < lensub)//当两个字符串都没遍历完
	{
		if (j==-1||s[i] == sub[j])//匹配成功,往后走继续匹配
		{
			i++;
			j++;
		}
		else
		{
			j = next[j];//匹配失败,回到该位置next数组代表的下标位置
		}
	}
	free(next);
	next = NULL;
	if (j >= lensub)
	{
		return i - j;
	}
	else
	{
		return -1;
	}
}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值