自己实现了下kmp算法,感觉失败的地方要反复比较,这个比较浪费:
public class KMP {
public static int[] calcNextArray(char[] target) {
int[] next = new int[target.length];
next[1] = 0;
for (int i = 2; i < target.length; ++i) {
int j = next[i - 1];
while (target[j] != target[i - 1] && j != 0) { j = next[j]; }
next[i] = (target[j] == target[i - 1] ? (j + 1) : 0);
}
return next;
}
public static int findStr(char[] str, char[] target) {
int[] next = calcNextArray(target);
int i = 0, j = 0;
for (; ;) {
if (str[i] == target[j]) {
++i;
++j;
if (i >= str.length || j >= target.length) {
break;
}
} else if (j == 0) {
++i;
if (i >= str.length) {
break;
}
} else {
j = next[j];
}
}
if (j == target.length) {
return i - target.length;
}
return -1;
}
}
做了一下简单的单元测试:
public class KMPTest {
@Test
public void testNextArray() {
String target = "abacab";
int[] next = KMP.calcNextArray(target.toCharArray());
assertEquals(next[1], 0);
assertEquals(next[2], 0);
assertEquals(next[3], 1);
assertEquals(next[4], 0);
assertEquals(next[5], 1);
target = "aaabaaa";
next = KMP.calcNextArray(target.toCharArray());
assertEquals(next[1], 0);
assertEquals(next[2], 1);
assertEquals(next[3], 2);
assertEquals(next[4], 0);
assertEquals(next[5], 1);
assertEquals(next[6], 2);
}
@Test
public void testKMP() {
String str = "abacaabacabacabaabb";
String target = "abacab";
assertEquals(5, KMP.findStr(str.toCharArray(), target.toCharArray()));
}
}