KMP算法

Posted 不倒翁*

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了KMP算法相关的知识,希望对你有一定的参考价值。

1.KMP算法介绍

在计算机科学中,Knuth-Morris-Pratt字符串查找算法(简称为KMP算法)可在一个字符串 S 内查找一个词 W 的出现位置。 一个词在不匹配时本身就包含足够的信息来确定下一个匹配可能的开始位置,此算法利用这一特性以避免重新检查先前匹配的字符。是一个效率非常高的字符串匹配算法

2.KMP算法的解析

KMP算法主要分为两步:
第一步主要是求一个next数组,这个数组中存放者子串匹配失败后下一次开始匹配的位置。
第二步就是实现KMP算法的主体

2.1 怎么求next数组呢?

首先我给出一个这样的子串:abcabcda,r然后定义一个next数组长度和子串的长度一样,并设 next[0]=-1, next[1]=0. 这两个值是自己给定的,也可以设为其他值。
定义一个i = 2 来开始记录next数组标号,定义变量 k =0 来遍历子串,

那么怎么来求next的值呢?
好好理解接下来的这句话:
先找到当前子串中当前 i 的前一个字符,也就是 i-1 对应的字符,然后从头开始找,看从0开始到 i-1 的区间内,是否包含以第一个字符开始,和i-1对应字符相同的字符结束的子串,如果找到了,然后看找到的子串有几个元素,此时,next[i]就等于几。没找到就将 i++,然后接着找下一个。
看这句话可能有点难理解,下面跟着图对着看下




接下来步骤和算法都一样了。


下面就是代码的实现部分

void GetNext(char* sub, int* next, int lenSub)
{
	assert(sub != NULL);
	assert(next != NULL);
	next[0] = -1;
	next[1] = 0;
	int i = 2;
	int j = 0;
	while(i<lenSub)
	{
		if(k==-1 || sub[i-1]==next[k])
		{
			next[i] = k+1;
			k++;
			i++;
		}else
		{
			k = next[k];
		}
	}

}

2.2KMP算法的主要实现

/*
str: 主串
sub: 子串
pos: 主串中的查找位置
*/
int KMP(char* str, char* sub, int pos)
{
	assert(str!=NULL && sub != NULLL);
	int lenStr = strlen(str);
	int lenSnb = strlen(sub);
	if(lenStr == 0 || lenSub==0)
		return -1;
	if(pos<0)
		return -1;
	int* next = (int*)malloc(sizeof(int)*lenSub); //开辟next需要的空间
	GetNext(sub,next,lenSub); //获取next数组
	int i = pos;	//遍历主串
	int j= 0;	//遍历字串
	while(i<lenStr && j<lenSub)
	{
		if(k==-1 || str[i] == sub[j])//比较子串与主串元素是否相等
		{
			j++;
			i++;
		}else
		{
			j = next[j];	//子串与主串元素不相等,i不变,j后退,子串从next[j]下标开始遍历
		}
	}
	free(next);
	if(j >= lenSub)
		return i-j;
	else
		return -1;                                                         
}

以上是关于KMP算法的主要内容,如果未能解决你的问题,请参考以下文章

数据结构—串KMP模式匹配算法

Python ---- KMP(博文推荐+代码)

KMP算法及Python代码

KMP算法及Python代码

图解KMP算法原理及其代码分析

Kmp算法Java代码实现