读书人

【给数学糟糕的人的KMP】字符匹配教程

发布时间: 2013-01-26 13:47:03 作者: rapoo

【给数学不好的人的KMP】字符匹配教程(一)next数组的理解

终于接触了一丁点字符匹配的东西(其实也只是入门的KMP),话说这个东西的确需要很强的数学思维,其中NEXT数组尤其坑爹,很多ACMER就是栽在了这个数组上,不明觉厉。什么诸如“失配” “数组移位”和一些S(i-1)...之类的一长串字母的确让我们十分不爽。更有博客表示这个确实很难,此中有真意,欲辨已忘言云云。。算法导论上的模板是从1开始的,自己还写了个SString数据类型让好多人云里雾里,今天我们就来试着解释一下KMP的基本原理吧。

字符匹配的基本问题是寻找子串在一长串中的位置。比如

一长串s:abacababt

子串t:abab,返回值就是4.当然你要非说5也行。。

寻找这种东西的位置,最先想到的思路自然是暴搜。。我们用i来表示大串中当前查找的位置,j表示子串中当前查找的位置,开始都是0,然后开搜,条件很简单,s[i]==t[j]。。。

原理见图,【给数学糟糕的人的KMP】字符匹配教程(一)next数组的理解

代码如下:


这个数组可以使用搜索的方法得到。网上的教程质量参差不齐,这里给出一个能用的。下标从0开始,next[0]默认为0,获得的数组可以使用调试功能查看。

int next[1000];void build_next(string b){ int i,j=0,key=0;    memset(next,0,sizeof(next));    for(i=1;i<b.size();i++)    {        j=next[i-1];        while(j==1 && b[i]!=b[j])        {        j=next[j-1];        }        if(b[j]==b[i])        {            next[i]=j+1;        }        else next[i]=0;    }}

这个数组的理解与否是掌握KMP的关键,具体怎么使用,下篇文章会给出更新。

1楼shihui142857昨天 23:14
这么关键的算法next_build()都没有个注释吗?
Re: mig_davidli昨天 09:35
回复shihui142857n就是先将next置0(网上的教程版本有两种,一种是next[0]=0,next[1]=1,next[2]=其他..另一种是next[0]=-1,next[1]=0,next[2]=其他...我的是next[0]=0,next[1]=0..)n第一行是j的初始化,J的意思是根据前面已知的next值来判断新加的那一个字符是否相等,不等则回溯。nwhile()的作用是说如果找到相同的一个前缀和后缀字符,则根据前面的next[j]值来判断是加一还是置零。n后面的两个判断是表明了next[j+1]和next[j]的关系,只有两种,要么加一,要么置零。就是说 一个确定的字符串加入一个字母之后,要么匹配的更多了,要么完全不匹配了。

读书人网 >编程

热点推荐