朴素算法和KMP算法
public class 朴素算法 {
public static void main(String[] args) {
String str = "BBC ABCDAB ABCDABCDABDE";
String target = "ABCDABD";
boolean res = method(str, target);
System.out.println(res);
}
private static boolean method(String str, String target) {
int i = 0;//str下标
int j = 0;//target下标
char[] char_str = str.toCharArray();
char[] char_tartget = target.toCharArray();
while (i < char_str.length && j < char_tartget.length) {
if (char_str[i] == char_tartget[j]) {
//若该点匹配 则都向后移动一位
i++;
j++;
} else {
//若不匹配 则i回溯 减去j并加1 j为移动的步数 加1是为了后移一位
i = i - j + 1;
j = 0;
}
}
if (j == char_tartget.length) {
return true;
} else {
return false;
}
}
}
public class KMPNext {
public static void main(String[] args) {
String s="CAABCDABDD";
String p = "ABCDABD";
int[] next = getNext(p);
System.out.println(Arrays.toString(next));
int num = KMPSearch(s, p, next);
System.out.println(num);
}
public static int[] getNext(String str) {
char[] char_str = str.toCharArray();
int[] next = new int[char_str.length];
// 第一个值为-1 固定
next[0] = -1;
int k = -1;
int j = 0;
while (j < char_str.length - 1) {
// char_str[k]表示前缀,char_str[j]表示后缀
if (k == -1 || char_str[j] == char_str[k]) {
++k;
++j;
if (char_str[j] != char_str[k])
next[j] = k;
else
// 因为不能出现p[j] = p[ next[j ]],所以当出现时需要继续递归,
// k = next[k] = next[next[k]]
next[j] = next[k];
// System.out.println(Arrays.toString(next));
} else {
// 不断的递归k = next[k],直到要么找到长度更短的相同前缀后缀,
// 要么没有长度更短的相同前缀后缀
k = next[k];
}
}
return next;
}
public static int KMPSearch(String s,String p,int[] next) {
int i=0;
int j=0;
char[] char_s = s.toCharArray();
char[] char_p = p.toCharArray();
while(i<char_s.length&&j<char_p.length) {
//如果j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++
if(j==-1||char_s[i]==char_p[j]) {
i++;
j++;
}else {
//如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j]
//next[j]即为j所对应的next值
j=next[j];
}
}
if(j==char_p.length) {
return i-j;
}else {
return -1;
}
}
}
如果已知next[j] = k,如何求出next[j+1]呢?具体算法如下:
// 1. 如果p[j] = p[k], 则next[j+1] = k + 1;
// 2. 如果p[j] != p[k], 则令k=next[k],如果此时p[j]==p[k],则next[j+1]=k+1,
// 如果不相等,则继续递归前缀索引,令 k=next[k],继续判断,直至k=-1(即k=next[0])或者p[j]=p[k]为止