KMP算法C 代码代码实现

最近做了一道题是叫写出一个字符串的nextval数组,其实我是知道next数组的含义的,上网搜了一下很着急,因为全部都在讲怎么求nextval和next数组,却没有一个讲清楚了nextval究竟是个什么东东,大概看了下求法,然后又自己按照next数组实现了一下kmp,顿时领悟了那个nextval是什么,不过其实这个数组用处不是太大。

        牛客网请的左程云老师的课听了也非常清晰,虽然听了又忘,还是自己懒惰懒于写代码,今天终于写成了。注意有个区别,我实现的kmp是寻找出现的次数,所以当匹配成功后还要继续匹配,所以我的next数组长度是(匹配字符串ms的长度+1)。

       《KMP算法C 代码代码实现》

#include "stdio.h"
#include "stdlib.h"
#include "string.h"

//求next数组
int * getNextArray(char *ms)
{
	int *next = (int*)malloc(sizeof(int)*(strlen(ms)+1));
	if(strlen(ms) == 1)
	{
		*next = -1;
		return next;
	}
	next[0] = -1;
	next[1] = 0;
	int pos = 2;
	int cn  = 0;
    while(pos <= strlen(ms))
	{
		if(ms[pos-1] == ms[cn])
			next[pos++] = ++cn;  //1
		else if(cn>0)
			cn = next[cn];       //2
		else
			next[pos++] = 0;     //3
	}
	for(int i=0; i!=strlen(ms)+1; i++)
		printf("next[%d] = %d\n", i, next[i]);
	return next;
}
//要么pos增加, 要么pos-cn增加

int KMPmatch(char *ms, char *str)
{
	int *next = getNextArray(ms);
	int count = 0;
	int msl  = strlen(ms);
	int strl = strlen(str);
	if(msl>strl)
		return 0;
	int mspos = 0;
	int strpos = 0;
	while(strpos < strl)
	{
		if(ms[mspos] == str[strpos])
		{
			mspos++,strpos++;           //4
			if(mspos == msl)
				count++;
			if(strpos == strl)
				return count;
		}
		else{
			if(mspos == 0){
				strpos++;           //5
				if((strl-strpos) < msl)
				    return count;
			}
			else
				mspos = next[mspos];   //6
		}
	}
}
//要么ms数组在往前推,要么pos往前走,时间复杂度最多为O(2N);

int main()
{
	char *ms =  "aab";
	char *str = "aaabaaacaaab";

	printf("%d", KMPmatch(ms, str));
	return 0;
}

关于时间复杂度的严肃证明,准备翻一下算导,但是发现算导的语言风格自己很不适应根本看不下去,于是在这里重述一下左程云老师的通俗证明法。

1.求next数组,设ms串长度为M,我们可以看到pos和(pos-cn)都属于范围[0,M],

   注释为1的分支   pos增加    (pos-cn)不变

   注释为2的分支   pos不变     (pos-cn)增加—由于cn减少

   注释为3的分支   pos增加       (pos-cn)增加

    三个分支都是让pos或者(pos-cn)增加,那么循环次数肯定小于2M次,所以求next数组的时间复杂度为O(M);

2.KMP过程时间复杂度

   注释4和5都是使strpos增加,而注释6的地方会让匹配字符串在str上的左边界(即strpos – mspos)往右推移(即增加),而这两个变量也都是[0,n]范围内的,所以循环次数肯定小于2N

    故而时间复杂度为O(N);

 最近看了libevent源码,愈发觉得数据结构和算法的重要性,

 又翻看了以前收藏或者转载的博客,却发现自己又有新的收获,在我的前半生我总是不断去追逐新的东西,但是转头发现自己收获的确实不多,温故而知新,自己要加油了。

    原文作者:KMP算法
    原文地址: https://blog.csdn.net/uestczshen/article/details/54917223
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞