KMP算法用来解决字符串匹配问题。
要理解KMP算法,首先要理解部分匹配值的概念。
对于一个字符串,我们先讨论它自身的性质——“前缀”和“后缀”:
前缀是指除了最后一个字符以外,一个字符串的全部头部组合;
后缀是指除了第一个字符以外,一个字符串的全部尾部组合。
部分匹配值就是前缀和后缀的最长共有元素的长度。
例
1)A的前缀为无,后缀为无,所以部分匹配值为0.
2)AA的前缀为A,后缀为A,两个相等,所以部分匹配值为1.
3)ABCDABD的前缀为ABCDAB,ABCDA,ABCD,ABC,AB,A,后缀为BCDABD,CDABD,DABD,ABD,BD,D.所以部分匹配值为0.
4)ABCDAB的前缀为ABCDA,ABCD,ABC,AB,A,后缀为BCDAB,CDAB,DAB,AB,B.所以部分匹配值为2.
接下来用一个算法获取一个字符串的部分匹配值表
//获取字符串的部分匹配值表
public static int[]kmpnext(String dest){
//创建一个next数组,保存部分匹配值
int next[]=new int[dest.length()];
next[0]=0;//字符串的长度为1的部分匹配值为0
for(int i=1,j=0;i<dest.length();i++) {
while(j>0&&dest.charAt(j)!=dest.charAt(j)) {
j=next[j-1];
}
//dest.charAt(i)==dest.charAt(j),部分匹配值加一
if(dest.charAt(i)==dest.charAt(j)) {
j++;
}
next[i]=j;
}
return next;
}
KMP算法的精髓在于:当匹配过程中产生“失配”时,移动位数=已匹配的字符数-对应得部分匹配值。
```java
public static int kmp(String str1,String str2,int[] next) {
for(int i=0,j=0;i<str1.length();i++) {
while(j>0&&str1.charAt(i)!=str2.charAt(j)) {
j=next[j-1];
}
if(str1.charAt(i)==str2.charAt(j)) {
j++;
}
if(j==str2.length()) {
return i-j+1;
}
}
return -1;
}