KMP是字符串匹配的常见算法有多种变形,下面仅仅讨论下经典的KMP算法:
a) kmp算法主要是先计算Pattern串p的特性,利用的是一个nextPos[]数组。
1)nextPos[0] == -1;
2)如果nextPos[j] == k,则:'p0 ... pk-1' == 'pj-k+1 ... p j-1' (1<k<j)。且没有k' > k满足此等式,即k是最大的。
3)如果nextPos[j]==k,那么假如主串的当前char和pattern的第j个char不匹配,那么Pattern向前移动,使得主串当前char和Pattern的第k个比较,如果成功则继续匹配,如果不成功则Pattern按照nextPos[k]==s继续移动,如此循环。
4)原因:1. 在2)中等式可以保证串'p0 ... pk-1' 必然匹配。2. 由于k是最大的所以保证了正确性。
5)问题就集中在如何求nextPos数组。首先其过程也是一个匹配过程和主匹配极其相似。整个Pattern既是主串又是模式串。
6)nextPos由自“底”向“上”求得。极像动态规划过程:nextPos[i+1] = nextPos[i] + 1 (pk == pi)
nextPos[m] + 1 (pm != pi)
m动态求得(见程序的注释)。求到的nextPos[n]==k必定是满足2)中等式的最大k(最优子结构!!)。此便是bellman动态规划过程!仔细体会下。
b) setPattern函数中有语句 (注释attention)
if(pattern.charAt(i) != pattern.charAt(j)){
nextPos[i] = j; //如果不等则有机会和主串的当前字符匹配
}else{
nextPos[i] = nextPos[j]; //在相等的情况下,既然charAt(i)不匹配则charAt(j)也不匹配,继续向前找。
} //由于等价的传播,只要向前一次即可。
和最基本的KMP算法等价语句比较:
nextPos[i] = j;
多加一个if语句判断是一个小技巧,由于nextPos[i]==j,是当主串当前字符和pattern.charAt(i)“失”配的情况下,Pattern要向右移动,直到Pattern的第j个字符和主串当前字符比较,那么如果pattern.charAt(i) == pattern.charAt(j) 则主串当前字符和 pattern.charAt(j)也必然“失”配,所以在这种情况下用最基本的KMP就会进行不必要的比较了。
c) if(j == -1 || mainString.charAt(i) == pattern.charAt(j))里面有bool表达式的短路判断才能使得charAt(j)永远不会等于-1
上面是我的考虑,代码下有KMP比较经典的介绍:
-------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------
http://blog.csdn.net/Oneil_Sally/archive/2008/12/03/3440784.aspx
严蔚敏版数据结构80页