KMP字符串匹配算法学习总结

来源:互联网 发布:河南软件开发公司 编辑:程序博客网 时间:2024/05/22 00:07

近学长讲了KMP算法,又叫看毛片算法。当时也没大听懂,关键是没听明白next数组怎么求的。于是只能回来自学了。其实KMP确实有些难以理解,而且不好表达,所以看网上的讲解也是看不太明白,但是有幸看到了两篇非常优质的讲解,方才醍醐灌顶。
还有一点要提示一下,不同的教程对于next数组的定义方式可能不同,next[n]有的定义为前n-1的字符的最长公共前后缀,有的定义为前n个字符的最长公共前后缀。这个没有对错之分,只不过下标有偏移而已。

KMP原理介绍(图文并茂,通俗易懂):http://kb.cnblogs.com/page/176818/

Next数组求解(KMP最难理解的部分):http://blog.csdn.net/yearn520/article/details/6729426

现在说说我自己对KMP的理解:

KMP最关键的一点思想就是:利用已经匹配的字符信息,减少匹配失败时的重复比较。

如何利用已经匹配的信息很关键,所以利用了Next数组存储"前缀"和"后缀"的最长的共有元素的长度。

已匹配的后缀必然与文本串相同,而前缀又与后缀存在相同部分,所以可以跳过前缀这部分的比较。这也是KMP算法的精华所在。

对于Next的求解是非常关键的,如果暴力求解的话那就不叫KMP算法了。

其实还是要用到KMP的思想的,利用已经匹配的字符信息,减少匹配失败时的重复比较。

其实还要利用动态规划的思想,对于求解数组next,只需考虑next[n-1]->next[n] 的转化。

1.当text[next[n-1]+1]==text[n] 时 

next[n]=next[n-1]+1

2.如果不相等,即匹配失败。

那么就要利用KMP思想,

利用判断 next[next[n-1]+1] =? text[n]   继续1.或2.直到串结束

具体细节参见第二篇文章。

现在觉得KMP真的是一个非常优雅的算法,不论是在思想上还是在代码表达上,都十分优雅。

void getnext(){    int i=0,j=-1;    next[0]=-1;    while(i<m)    {        if(j==-1||pat[i]==pat[j])        {            i++,j++;            next[i]=j;        }        else j=next[j];    }}int kmp(){    int i=0,j=0;    getnext();    while(i<n)    {        if(j==-1||text[i]==pat[j])        {            i++,j++;            if(j==m) break;        }        else j=next[j];    }    if(j==m) return i+1-m;    else return -1;}



0 0