KMP算法详解

KMP算法短短几行,却比较难理解,今天刷题碰到了,研究了一下午,拿出来跟大家分享一下

比如判断ABCABCGHA是不是ABCABCFABCD的字串

普通的思路是

KMP算法详解_第1张图片

这是进行比较的普通的思路,当比较到E不相等时,进行从第二位进行比较,如上图中的第二个。

KMP的精华在于如果目标字符串中有重复的,接下从重复的的下一个进行比较,如下图

KMP算法详解_第2张图片

既然是从重复的进行记录,那么就必须有数组进行记录重复的次数我们通常定义next[]数组,next数组的含义如下图

KMP算法详解_第3张图片

以上图的含义是从0开始,查找前面是否有与自己重复的,有的话记1,再有的话记2,比较的是前缀与后缀的大小,ABCAB,前缀有A,AB,ABCA后缀有B,AB,CAB,BCAB,当处于B的位置时,正好前缀AB与后缀AB相等,所以记为2,依次类推

含义明白了,直接上代码

void makeNext(char str[],int next[]){
	int length = strlen(str);
	next[0] = 0;
	int index,int k;//一个是str的下标,k是最大前后缀的长度
	for(index = 1,k = 0;index < length;++index){
		while(k > 0 && str[index] != str[k])//前后缀不相等,比较之前相等的,见下图理解
			k = next[k - 1];
		if(str[index] == str[k]) //前后缀如果相等,将k加1,对应上图
			++k;
		next[index] = k;
	}
}
k = next[k-1]这一步最难理解,请看下图 KMP算法详解_第4张图片

每次比较就是从前面的寻找最大的前后缀长度,由于左侧与右侧相等,所以左侧的最大前后缀长度后面的那一个比如
str[2] = E与最后的E进行比较。

str[6]时,k = 0,所以str[11] k = 5;

next数组的作用以及代码就这样,下面看如何通过next数组与主字符串进行比较

bool kmp(int target[],int src[],int next[])
{//target 指的的主字符串 src指的是目标字符串,判断src是否在target中
	int lengthTarget = strlen(target);
	int lengthSrc = strlen(src);
	makeNext(src,next);
	int i;
	int lengthOfCompare;
	for(i = 0,lengthOfCompare = 0; i< lengthTarget;++i){
		while(lengthOfCompare > 0 && target[i] != src[lengthOfCompare])
			lengthOfCompare = next[lengthofCompare - 1];//不等正好从
		//前面最大的前后缀的下一个进行比较
		if(target[i] == src[lengthOfCompare])
			++lengthOfCompare;
		if(lengthOfCompare == lengthSrc)
			return true;
	}
}
好了,就这些了,就这么简单




你可能感兴趣的:(KMP算法详解)