LeetCode-28-找出字符串中第一个匹配项的下标

LeetCode-28-找出字符串中第一个匹配项的下标_第1张图片

1、KMP算法

解决本问题最简单的方法就是暴力穷举,思路简单但时间复杂度为 O ( m ∗ n ) O(m*n) O(mn)。此处我们仅考虑最优的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==1p[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;
    }
};

你可能感兴趣的:(LeetCode刷题记录,LeetCode-待复习,leetcode,算法,职场和发展)