package algorithm;
public class KMP {
public static void main(String[] args) {
// TODO Auto-generated method stub
//abcbfedabfea
//abfeab
//000012
String str = "hello worlbaawworld";
String pattern = "world";
int index = search(str, pattern, next(pattern));
System.out.print(index);
}
public static int search(String str, String pattern, int[] next) {
for (int i = 0, j = 0; i < str.length(); i++) {
while (j > 0 && str.charAt(i) != pattern.charAt(j)) {
//前缀是从前往后的,如果next[j - 1]=2,说明从模式串索引0开始,刚好有两个相等(公共)前后缀,
//也就是模式串0,1位置是相同的,我们回退的位置在
//前缀的后面一位,索引刚好是2,也就是说next[j - 1]的值,刚好等于回退的索引位置。当j==0时说明不能再回退了,这个时候只有把
//主串的索引向后移动
j = next[j - 1];
}
if (str.charAt(i) == pattern.charAt(j)) {
j++; // 连续匹配的个数
}
if (j == pattern.length()) {
return i - j + 1;
}
}
return -1;
}
public static int[] next(String pattern) {
int[] next = new int[pattern.length()];
//初始化为0,第一个没有公共前后缀,i=1,j=0错开
//模式串和模式串进行比较,一次计算出前缀表
next[0] = 0;
for (int i = 1, j = 0; i < pattern.length(); i++) {
while (j > 0 && pattern.charAt(i) != pattern.charAt(j)) {
j = next[j - 1];
}
if (pattern.charAt(i) == pattern.charAt(j)) {
j++; // 连续匹配的个数
}
next[i] = j;
}
return next;
}
}