在LeetCode上做题时遇到了字符串匹配问题,之前没有学过KMP算法,于是参考了网上的文章学习了该算法,现记录如下。
KMP算法的主要难点:
- 最长相等前后缀,通过next数组记录
- next数组构造过程中会回溯,具体可看上面提及的文章
class Solution {
public int kmp(String s, String t) {
int m = s.length(), n = t.length();
int[] next = new int[n];
getNext(t, next);
int i = 0, j = 0;
while (i < m && j < n) {
if (j == -1 || s.charAt(i) == t.charAt(j)) {
i++;
j++;
}
else j = next[j];
}
if (j >= n) return i - n;
else return -1;
}
public void getNext(String t, int[] next) {
int j = 0, k = -1, n = t.length();
next[0] = -1;
while (j < n - 1) {
if (k == -1 || t.charAt(j) == t.charAt(k)) {
j++;
k++;
next[j] = k;
}
else k = next[k];
}
}
}
改进后的KMP算法:
class Solution {
public int kmp(String s, String t) {
int m = s.length(), n = t.length();
int[] nextVal = new int[n];
getNextVal(t, nextVal);
int i = 0, j = 0;
while (i < m && j < n) {
if (j == -1 || s.charAt(i) == t.charAt(j)) {
i++;
j++;
}
else j = nextVal[j];
}
if (j >= n) return i - n;
else return -1;
}
public void getNextVal(String t, int[] nextVal) {
int j = 0, k = -1, n = t.length();
nextVal[0] = -1;
while (j < n - 1) {
if (k == -1 || t.charAt(j) == t.charAt(k)) {
j++;
k++;
if (t.charAt(j) != t.charAt(k)) nextVal[j] = k;
else nextVal[j] = nextVal[k];
}
else k = nextVal[k];
}
}
}