KMP算法讲得很好的文章:
https://www.cnblogs.com/dusf/p/kmp.html
KMP算法的核心就是找出要移动的位数
移动位数 = 已匹配的字符数 - 对应的部分匹配值
A B C D A B D
0 0 0 0 1 2 0
6 - 2 = 4
所以向后移动位数是4
串的模式匹配-KMP算法分两步
1、得到子串的部分匹配表(注意对象是子串)
2、使用得到的部分匹配表来找到在主串中的索引
所以KMP的难点比较绕的地方就是得到子串的部分匹配表
在上面分享的那篇文章里解释得很清楚,强烈建议大家去看。
package KMPAlgorithm;
import java.util.Arrays;
public class KMPAlgorithm {
//串的模式匹配算法-KMP算法的核心两步:
//1、得到子串的部分匹配表
//2、使用部分匹配表,完成KMP匹配
public static void main(String[] args) {
String s1 = "BBC ABCDAB ABCDABCDABDE";
String s2 = "ABCDABD";
int next[] = get_next(s2);
System.out.println("next =" + Arrays.toString(next));//0, 0, 0, 0, 1, 2, 0
int index = Index_KMP(s1,s2,next);
System.out.println("index ="+index);//15
}
//1、得到s2的部分匹配表
public static int[] get_next(String s2) {
int[] next = new int[s2.length()];
next[0] = 0;//next的首个元素一定是0,因为[a]一个元素的时候的共有元素长度是0
for(int i = 1, j = 0; i < s2.length(); i++) {
while(j > 0 && s2.charAt(i) != s2.charAt(j)) {//处理不相等的情况
j = next[j-1];//KMP算法的核心处!!!!!!
}
if(s2.charAt(i) == s2.charAt(j)) {//处理相等的情况
j++;
}
next[i] = j;
}
return next;
}
//2、进行串的模式匹配,使用1、中得到的部分匹配表
public static int Index_KMP(String s1, String s2, int[] next) {
for(int i = 0, j = 0; i < s1.length(); i++) {
while(j > 0 && s1.charAt(i) != s2.charAt(j)) {
j = next[j-1];//核心处
}
if(s1.charAt(i) == s2.charAt(j)) {//处理能够匹配上的情况
j++;
}
if(j == s2.length()) {//当完成匹配时
return i-j+1;//返回索引
}
}
return -1;//无法找到匹配
}
}