kmp主要是next数组的构造
next[i]等于str[0–(i-1)]的字符串的前缀和后缀的最大匹配值。
通过next数组的加速过程:
public static int getIndexOf(String s,String t) {
if(s==null||t==null||s.length()<1||t.length()<1||s.length()<t.length())
return -1;
char[] source=s.toCharArray();
char[] target=t.toCharArray();
int i1=0;
int i2=0;
//得到next数组,该数组表示:如果当前位置i,则表示0到i-1的前缀和后缀的最大匹配长度
int[] next=getNextArray(target);
//while可以加上这个source.length-i1>=target-i2,如下面的也可以
while(i1<source.length&&i2<target.length) {
//两个字符相等
if(source[i1]==target[i2]) {
i1++;
i2++;
}
//字符不相等,当target的首字符就不相等时,i1++就行了
else if(next[i2]==-1) {
i1++;
}
//字符不相等,当不是target的首字符不相等,则i2根据next数组来跳转
else {
i2=next[i2];
}
}
return i2==target.length?i1-i2:-1;
}
next数组的求解:
public static int[] getNextArray(char[] str) {
if(str.length==1)
return new int[] {-1};
int[] next=new int[str.length];
//0位置之前的匹配长度置为-1
next[0]=-1;
//1位置之前的匹配长度置为0,因为不存在前缀和后缀
next[1]=0;
//从i=2开始完成next数组的构造
int i=2;
//cn表示next数组中跳转过程中的索引位置,因为next[i]的大小可以根据next[i-1]来确定,如果str[i-1]==str[cn],则next[i]=next[i-1]+1;
//否则cn=next[cn]
//cn=next[1];
int cn=0;
while(i<next.length) {
if(str[i-1]==str[cn]) {
next[i++]=++cn;
}
//cn此时不能为0
else if(cn>0) {
cn=next[cn];
}
else {
next[i++]=0;
}
}
return next;
}