
解决本问题最简单的方法就是暴力穷举,思路简单但时间复杂度为O(m∗n)O(m*n)O(m∗n)。此处我们仅考虑最优的KMP算法,时间复杂度为O(m+n)O(m+n)O(m+n)。
KMP算法的优化之处在于当我们对比haystackhaystackhaystack和needleneedleneedle时,当出现某一位上的字符不对应时,暴力穷举的方法是将needleneedleneedle重新从第0位开始进行匹配,而KMP算法则是跳到之前遍历的一个位置上继续进行遍历。
值得注意的是,为了确定当haystackhaystackhaystack和needleneedleneedle不匹配时我们需要跳到哪一位上,我们使用数组nextnextnext来进行记录当needleneedleneedle中第jjj位不匹配时需要跳转的位置next[j]next[j]next[j]。很显然,当j=0j=0j=0时,我们不用进行匹配,故next[0]=−1next[0] = -1next[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 getNext(string p) {vector 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 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;}
};