您的位置:首页 > 其它

KMP算法详解

2016-04-27 22:06 260 查看
KMP算法短短几行,却比较难理解,今天刷题碰到了,研究了一下午,拿出来跟大家分享一下

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

普通的思路是



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

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



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



以上图的含义是从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]这一步最难理解,请看下图


每次比较就是从前面的寻找最大的前后缀长度,由于左侧与右侧相等,所以左侧的最大前后缀长度后面的那一个比如

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;
}
}
好了,就这些了,就这么简单
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: