首先是next()函数,用于求出来每次匹配的移动规律,在此不得不感叹先人的牛逼思维。详情见下:
public class KMP模式匹配算法 {
static SeqString s = new SeqString("abcdefghijklmnopqrstu");
static SeqString a = new SeqString("stu");
public static void main(String[] args) {
System.out.println(index_KMP(a, 1));
}
public static int index_KMP(IString T, int start) {
int[] next = getNext(T);
int i = start;
int j = 0;
while (i < s.length() && j < T.length()) { // 循环,查找对比
if (j == -1 || s.charAt(i) == T.charAt(j)) {// 如果匹配字符j=-1表示S[i]!=T[0],子字符串中没有出现相等的项
i++; // 转下一个 字符 //最喜欢的情况,按照BruteForce算法匹配
j++; // 每次匹配成功,j+1;
} else { // S[i]!=T[j]时
j = next[j]; // 子字符串移动,再次匹配
}
}
if (j < T.length()) { // 匹配失败
return -1;
} else { // 匹配成功
return (i - T.length());
}
}
private static int[] getNext(IString T) { // 用于在子字符串和主字符串匹配过程中失配后,确认子字符串的从何处开始匹配主字符串
int[] next = new int[T.length()]; //主要是为了求出各个字符对应的k值,k值决定了他们下次移动的位置
int j = 1;
int k = 0; // next[]为k在不同j条件下的值
next[0] = -1;// 第一项为空,设为-1
next[1] = 0;// 第二项如果不匹配,只能是第一项
while (j < T.length() - 1) {
if (T.charAt(j) == T.charAt(k)) { // 如果匹配,子字符串中出现相等的项,可以减少匹配次数
next[j + 1] = next[j] + 1; //设置下一项的k值
j++; // 主字符串指针
k++; // 子字符串指针,与next[j]同时+1,为之后准备
} else if (k == 0) { // 没有出现相等的项
next[j + 1] = 0; // 设置他的next[j+1]为0
j++;
} else { //如果没出现相同的,则k等于由if产生的next[k];
k = next[k];
}
}
return (next); // 返回next值
}
}