代码改变世界

初涉KMP算法

2016-11-08 22:56  Hold_F  阅读(172)  评论(0)    收藏  举报

      做了几道题之后,总结几个自己认为的重点吧。

      算法是为了解决在文本串中寻找模式串的问题。常规暴力方法,是在文本串(m)中遍历每个位置作为开始和模式串(n)进行匹配,时间复杂度O(mn)。而KMP的做法,是先对模式串进行一个预处理,使复杂度降到O(m+n)。

      算法的核心就是对模式串进行预处理,构造一个名为next的前缀数组。

      定义nxt[i]为模式串中第i个字符失匹配后指向的位置,或者说位置i之前的字符串的前缀和后缀公共部分的最大长度。

好理解一点的写法:

 

void getNext(char *p){
	int j = 0,k = -1;              
	int len = strlen(p);
	next[0] = -1;
	while(j < len){
		if(k == -1 || p[j] == p[k]){ //如处于初始位置,或者匹配成功
			j++;
			k++;
			next[j] = k;
		}
		else k = next[k];
	}
}

另一种简练点的写法:

void getNext(char * p){
	nxt[0] = -1;        
	int len = strlen(p); 
	for(int i = 0; i < len; i++){
		int k = nxt[i];
		while(k != -1 && p[i] != p[k]) k = nxt[k]; //如匹配不成功,就去找上一个位置尝试匹配
		nxt[i+1] = k + 1;
	}
}

KMP匹配函数

bool kmp(char *s, char *p){
	getNext(p);
	int lens = strlen(s), lenp = strlen(p);
	int i = 0, j = 0;
	while(i < lens && j < lenp){
		while(j != -1 && s[i] != p[j]) j = nxt[j];
		++i;
		++j;
	}
	if(j == lenp) return true;
	return false;
} 

 

 

总结KMP应用:

1、文本串中寻找模式串

2、串的前缀和后缀匹配问题

3、串的循环节问题

一句话来总结KMP,就是当匹配不成功时,模式串返回到失配字符前的最大相同前缀接着匹配的算法。