数据结构与算法-串(KMP匹配模式算法)

昨天有点小插曲,我们今天继续前天的字符串匹配模式算法,上次的朴素的匹配模式算法的效率非常低,于是我们想办法对它改进,前辈们就发现呀,如果要匹配的字符串前几位和后几位中某几位相同,前几位匹配失败的话,就可以直接跳过后几位的匹配过程,这样一来,效率就提高了,下面我们直接介绍前辈的kmp算法。我们设置一个数组next记住匹配字符串各个位置的j值。
next[j]=0,j=1;Max{k|1<k<j,且p1…pk-1=pj-k+1…pj-1}当此集合不为空时;1 其他情况。
例1:
j:123456
模式串T:abcdex
next[j]:011111
例2:
j:123456
模式串:ascasx
next[j]:01123
至于他怎么推导出来的,请看公式。
下面上代码:

//KMP模式匹配算法
 void get_next(string T,int *next)//初始化子串next数组 
 {
 	int i,j;
 	
 	i=1;
 	j=0;
 	
 	next[1]=0;
 	
 	while(i<T[0])
 	{
 		if(j==0||T[i]==T[j])
 		{
 			i++;
 			j++;
 			next[i]=j;
 			
		 }
		 else
		 	j=next[j];
	
	 }
 	
  } 
int Index_KMP(string S,string T,int pos)
{
	int i=pos;
	int j=1;
	int next[255];
	
	get_next(T,next);
	while(i<=S[0]&&j<=T[0])
	{
		if(j==0||S[i]==T[j])
		{
			i++;
			j++;
		}
		else
			j=next[j];
	}
	if(j>T[0])
		return i-T[0];
	else
		return 0;
	
 }

只有匹配串有重复kmp的又是才体现出来,后来有人发现kmp还有缺陷,还可以改进,例如匹配串的前部分和后部分的距离不变,当前半部分匹配成功后面出现匹配失败时,匹配字符串往下移动,其实一直到出现错误的部分就不用看了,不会匹配成功的,于是大佬又引入了nextval数组,用来记住next数组相等的部分去取代字符后续数组的值。不明白是吧,看个例子:
j:123456789
模式串:ababaaaba
next[j]:011234223
nextval[j]:010104210

明白了nextval就可以上代码啦:

//KMP算法再改进
 void get_nextval(string T,int *nextval)
 {
 	int i,j;
 	
 	j=0;
 	
 	nextval[1]=0;
 	while(i<T[0])
 	{
 		if(j==0||T[i]==T[j])
		{
			++i;
			++j;	
			if(T[i]!=T[j])
				nextval[i]=j;
			else
				nextval[i]=nextval[j];
			
		} 		
 		else
 			j=nextval[j];
	 }
 	
  } 

猜你喜欢

转载自blog.csdn.net/weixin_47644373/article/details/106244345