kmp算法刚开始看时都唔觉得那么难,大概是因为我以自己真正懂了,真是天真的小伙子。后来越看就越发现一切都不是那么简单
首先这是一个字符串匹配问题,现要在主串S中找子串T,对于普通的算法,相信没有人会不会的说。我这不是在教人(这一定要声明,那位大虾行过路过,还望指点一二)
只不过是想看完写下来,方便以后自己有用,毕竟自己写的东西自己看是容易理解很多的说
入正题,现在假设我们在匹配过程中,当到匹配到主串S的第i个字符与子串的第j个字符时出现所谓的“失配”,也就是S[i]!=[T[i],
并且有T的前j-1个字符“T[0]……T[j-1]" ==”S[i-j]……S[i-1]",此时必须去向右移动T串去寻找另外的匹配,在正常情况下(也就是最笨的方法)一般会反T串右移一位
然后回溯i,使得s[i-j+1]与T[1]比较,此时作向右移动一步的决定是因为我们总是认为只有向右移一步就可以找到匹配,假设我们真的移动一步就找到,也就是说当我们
找到匹配时那一定有“T[0]……T[j-2]" = "S[i-j+1]……S[i-1]",结全前式就有”T[0]……T[j-2]“ = ”T[j-1-(j-2)](T[2])……T[j-1]“(有点乱的,见谅,见谅),但大部份情况系
没有这种RP,移动一步后并不能得到匹配,没办法了,只能继续向右移动一步啦,我们总期待着下一步就是匹配,所以移动后我们又开始不厌其烦的开始匹配每一个T
中的字符是否与移动后对应的S串中的字符匹配,这样下去总有一步(总假设匹配是存在的,不然就没意思了)会出现这样的情况:T中的前k-1(0<k<j)个字符与主串
中的字符都对上了,此时我拉只要比较k-1个字符之后的情况即可,如果不匹配就再移一步咯(你妹,这不是很笨么?系噶),既然这种情况的出现是必然的,我们何不
一开始就把T串向右移动使T串的第K个字符T[k]与S[i]比较呢(靠,浪费这么多力气,这样不是就可以不用回溯i了吗?)。好!这都被我发现了(开玩笑,kmp他们早就知
道了,我也是抄下吧了),我就假设匹配进行到”T[0]……T[j-1]" = “S[i-j]……S[i-1]”时,又假设把T串向右移动步使得T串的第k个字符与S[i]比较时有“T[1]……T[k-1]” = “S[i-k+1]……S[i-1]”,结合前式我们可以轻易推出“T[0]……T[k-1]” = “T[j-k]……T[j-1]”(这式到后面有用,这里可以无视先)。由于”T[0]……T[j-1]" = “S[i-j]……S[i-1]”,我们只需继
续进行比较T[k] 与S[i],如果他们相等,就继续比较T[k+1] 与S[i+1],如果他们不相等,则再以同样的方法向右移动。现在我们又又假设next[j] = k 表示当T也就是子串的第i个字
符与主串不匹配时,我们像上面所讲的那样把T子串向右移动K步,然后可以继续比较。现在剩下的问题是怎么求出对应的next[j];
先定义:next[j] = -1 当 j = 0时;
next[j] = k 当T[j]不能匹配时须把T串向右移动的距离(0 <k <j,这里的k必然是可能的最大的,因为这是我们一步一步移动T串第一次达到这样情况时的k)
next[j] = 0 除上面之外的情况
现在开始计论怎么去求next[i]:
先来看式:“T[0]……T[k-1]” = “T[j-k]……T[j-1]”(之前就说过他有用,现在来了),当达到这种情况时,k是唯一最大的,即不存在k1 〉k使:
“T[0]……T[k1-1]” = “T[j-k1]……T[j-1]”,这在定义也说过。所以可以看出next[j]的取值只与子串T自身有关而与主串S无关(这点很重要),也就是我们要求的是
当T[j] != S[i]时使“T[0]……T[k-1]” = “T[j-k]……T[j-1]”的最大值next[j] = k;
!!!注意现在我们的问题变成了另一个:求对于子串的每一个j对应的next[j]值这个值是与主串完全无关的,下面我们看下图哈:
图的数字仅代表们置,不是字符,如编号1.的图,T串的字符"“T[0] ……T[6]” = “T[1]……T[7]”,表示next[8] = 7;那么next[9]是什么呢?如果T[7] = T[8],则有
“T[0] ……T[7]” = “T[1]……T[8]”,可以推得next[9] = 8;如果不等只能把下面的那行向右移一步如图2,期待着"“T[0] ……T[6]” = “T[1]……T[8]”,如果成立则next[9] = 7;
如果也不成立,照此类推直到连“T[0]” = "T[8]",都不成立则next[9] = 0;到这里不识有没有意识到这同最初的两个串匹配很相似呢!!!其实就是可以看作成主串是T
子串也是T的一个匹配,而当前情况下也就是“T[0]……T[k-1]” = “T[j-k]……T[j-1]”,要求nesxt[j+1]的值,只要按前面的方法(讲两个字符串匹配时),匹配就可以
得到next[j+1];由期定义出发就可以先预处理好next[i];用一个数组来保存对应的每一个next[]值;
以上只是个人愚见,大牛路过求指点