KMP算法

分析:第一次看这个算法的时候觉得应该还算简单,真正写的时候才发现,涉及了很多种情况,要完整弄清楚还真不是件简单的事情

引用百度百科:KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息。

这个算法的难点在于计算next[],也就是最大前缀后缀,

比如字符串ptr ,ababaca,长度是7,next[0],next[1],next[2],next[3],next[4],next[5],next[6]的值分别对应的是a,ab,aba,abab,ababa,ababac,ababaca的长前缀后缀的长度,

最长前缀后缀是“”,“”,“a","ab","aba","","a",next数组的值为{-1,-1,0,1,2,-1,0}


接下来,以图的方式,分别介绍四种情况


第一种

模式串和目标串到第5号位置S[5]='d',T[5] = 'z'不匹配,此时由于模式串5位置前不存在最大前缀后缀,所以j直接回溯到位置1,重新开始遍历


第二种

模式串和目标串到第5号位置S[3]='w',T[3] = '.' 不匹配,此时由于模式串2位置前存在最大前缀后缀 w ,所以j直接回溯到位置2,重新开始遍历


第三种

模式串和目标串到第5号位置S[6]='s',T6] = 'c' 不匹配,此时由于模式串6位置前存在最大前缀后缀 bb ,所以j直接回溯到位置3,重新开始遍历

第四种

模式串和目标串到第5号位置S[5]='x',T[5] = 'c' 不匹配,此时由于模式串5位置前存在最大前缀后缀sss ,所以j直接回溯到位置4,重新开始遍历



我们发现,KMP算法的关键在于得出next[],由以上分析我们得出next[]

计算next[]

void nextArr(char *pArr,int pLen,int *next)
{
	int k = -1;//k初始化为-1
	next[0] = -1;//-1表示没有最大前缀后缀
	for(int i=1; i<=pLen-1; i++)
	{
		while(k>-1 && pArr[k+1]!=pArr[i])//如果下一个元素不同k变为-1,回到模式串头
		{
			k = -1;
		}
		if(pArr[k+1]==pArr[i])//如果相同k++
		{
			k++;
		}
		next[i] = k;//这里把k即相同最大前缀后缀值的长赋给next[i]
	}
}

KMP匹配

void KMP(int *next,char *pArr,int pLen,char *arr,int len)
{
	int k = -1;//k初始化为-1
	
	for(int i=0; i<len; ++i)//从下标0开始对目标串匹配
	{
		while(k>-1 && pArr[k+1]!=arr[i])//模式串与目标串比较
		{	
			k = next[k];				//如果k>-1,且元素不相等,则k=next[k]回溯
		}
		if(pArr[k+1]==arr[i])			//如果元素对应相等,k++
		{
			k++;
		}
		if(k==pLen-1)					//当k = pLen-1,说明模式串匹配成功
		{
			k = -1;
			printf("i = %d\n",i-pLen+1);//打印匹配成功的位置
		}
	}
}

main调用测试

int main(void)
{
	char parr[10] = "aba";
	char arr[20] = "aababcabac";
	int next[10];
	nextArr(parr,3,next);
	KMP(next,parr,3,arr,10);

	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值