/**
* getNext 跟KMP一样
* KMP根据next[]数组进行匹配,next[]数组表示该位置的前面跟模式字符串相同的头部的长度是多少。
* getNext【next[0]==-1,也就是说进行getNext时,
* 就是进行模式串为本身模式串的前第一个字符。
* 且模式串会被不断的变长【长度为更新了next值的所有元素的个数】】
*/
public class KMP {
public static void main(String[] args){
String str="abcabcabdxy";
String mode = "abcabd";
int index = kmpIndex(str,mode);
System.out.println(index);
}
/**
* 通过模式串得到next[]数组 数组第一个元素的值为-1,第二个元素的值为0
* @param mode 模式串
*/
public static int[] getNext(String mode){
int[] next = new int[mode.length()];
next[0]=-1;
// next[] 数组考虑的是除当前字符外的最长相同前缀
int k=-1,j=0;//k表示相同前缀的最后一个的后一位,j表示当前元素的前一个
while(j<mode.length()-1){
if (k==-1||mode.charAt(j)==mode.charAt(k)){
next[++j]=++k;
}else {
k = next[k];
}
}
return next;
}
// 模式串是mode
public static int kmpIndex(String string,String mode){
int[] next = getNext(mode);
int i=0,j=0;
int m = mode.length();
int n = string.length();
while(i<m&&j<n){
if(i==-1||mode.charAt(i)==string.charAt(j)){
i++;j++;
}else {
//匹配失败了,但是失败的那个字母mode[j]的前缀【字母mode[j]的前几个】跟mode[i]的前缀一样的,所以只需要回到模式串的前next[i]个
// 因为此时模式串的前next[i]个字母跟要匹配的字符串的j位置的前next[i]一样。
i=next[i];
}
}
if (i==m)return j-1;
else return -1;
}
}