Leetcode28. kmp算法实现字符串匹配

Leetcode28. Implement strStr()

题目

Implement strStr().
Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.

解题分析

提到字符串匹配,就不得不提及kmp算法。kmp算法巧妙地消除了指针i的回溯问题,只需确定下次匹配j的位置即可,使得问题的复杂度由O(m*n)下降到O(m+n)。在kmp算法中,为了确定在匹配不成功时下次匹配时j的位置,引入了next[]数组,next[j]的值表示needle[0…j-1]中最长后缀的长度等于相同字符序列的前缀。
kmp算法的思想就是:在匹配过程中,若发生不匹配的情况,如果next[j]>=0,则目标串的指针i不变,将模式串的指针j移动到next[j]的位置继续进行匹配;若next[j]=-1,则将i右移1位,并将j置0,继续进行比较。
kmp算法的关键在于求算next[]数组的值,即求算模式串每个位置处的最长后缀与前缀相同的长度。
根据定义next[0]=-1,假设next[j]=k, 即needle[0…k-1]==needle[j-k,j-1]。若needle[j]==needle[k],则有needle[0..k]==needle[j-k,j],很显然,next[j+1]=next[j]+1=k+1。若needle[j]!=needle[k],则可以把其看做模式匹配的问题,即匹配失败的时候,可知k=next[k]。

源代码

class Solution {
public:
    int strStr(string haystack, string needle) {
        int size1 = haystack.size(), size2 = needle.size(), i = 0, j = 0;
        if (size2 == 0) {
            return 0;
        }
        int* next = new int[size2];
        getNext(needle, next);
        while (i < size1) {
            if (j == -1 || haystack[i] == needle[j]) {
                i++;
                j++;
            }
            else {
                j = next[j];
            }
            if (j == size2) {
                return i - size2;
            }
        }
        return -1;
    }

    void getNext(string s, int* next) {
        int j = 0, k = -1;
        next[0] = -1;
        while (j < s.size() - 1) {
            if (k == -1 || s[j] == s[k]) {
                j++;
                k++;
                next[j] = k;
            }
            else {
                k = next[k];
            }
        }
    }
};

以上是我对这道问题的一些想法,有问题还请在评论区讨论留言~

你可能感兴趣的:(leetcode算法)