1、KMP算法$$
解决本问题最简单的方法就是暴力穷举,思路简单但时间复杂度为 O ( m ∗ n ) O(m*n) O(m∗n)。此处我们仅考虑最优的KMP算法,时间复杂度为 O ( m + n ) O(m+n) O(m+n)。
KMP算法的优化之处在于当我们对比 h a y s t a c k haystack haystack和 n e e d l e needle needle时,当出现某一位上的字符不对应时,暴力穷举的方法是将 n e e d l e needle needle重新从第0位开始进行匹配,而KMP算法则是跳到之前遍历的一个位置上继续进行遍历。
值得注意的是,为了确定当 h a y s t a c k haystack haystack和 n e e d l e needle needle不匹配时我们需要跳到哪一位上,我们使用数组 n e x t next next来进行记录当 n e e d l e needle needle中第 j j j位不匹配时需要跳转的位置 n e x t [ j ] next[j] next[j]。很显然,当 j = 0 j=0 j=0时,我们不用进行匹配,故 n e x t [ 0 ] = − 1 next[0] = -1 next[0]=−1。而后:1、当 k = = − 1 ∣ ∣ p [ j ] = = p [ k ] k == -1 || p[j] == p[k] k==−1∣∣p[j]==p[k]时,说明此时前面存在和我们开始部分相同的字符串,我们可以直接使用;2、当 p [ j ] ! = p [ k ] p[j] != p[k] p[j]!=p[k]时,说明此时我们不能直接使用,我们只能查询上一个对应的位置。
class Solution {
public:
vector<int> getNext(string p) {
vector<int> next(p.length());
next[0] = -1;
int j = 0;
int k = -1;
while (j < (int) p.length() - 1) {
if (k == -1 || p[j] == p[k]) {
j++;
k++;
next[j] = k;
} else {
k = next[k];
}
}
return next;
}
int strStr(string haystack, string needle) {
int i = 0;
int j = 0;
vector<int> next = getNext(needle);
while (i < (int) haystack.size() && j < (int) needle.size()) {
if (j == -1 || haystack[i] == needle[j]) {
i++;
j++;
} else {
j = next[j];
}
}
if (j == (int) needle.length()) {
return i - j;
}
return -1;
}
};