对KMP的简单理解

对KMP的理解:

1,next 函数是KMP的核心。next[q]  表示模式 P 的前q位(对应下标 P[0,...,q-1])的最大前缀长度(不包括本身)。

      也就是若 next[q]=k,表示  P[0,...,k-1]=P[q-k,...,q-1].

     如:P="ababaca";   得到 next=[0,0,0,1,2,3,0,1]。注:next增加时只能+1。

2,当 P[k]!=P[q-1]时【下图中j 表示 q-1】,说明当前的最大前缀太大,不满足。必须变为除了此前缀之外最大的前缀   来测试,而次大前缀就是  next[k],即下图中的 B。(算法导论中有证明,没看!)

3,q==m表示模式中匹配完成。当前字符匹配时,最大前缀q++,再去匹配下一个字符;当前字符不匹配,说明该前缀太大,选择较小的前缀,q=next[q]。


/****************************************************************

代码:

class Solution{
public:
    int strStr(const string& s, const string &t){
        return kmp(s.c_str(), t.c_str());
    }
private:
    int kmp(const char *text, const char *pattern){
        const int n = strlen(text);
        const int m = strlen(pattern);
        vector<int> next(m+1, 0);
        compute_prefix(pattern, next);

        int q = 0;
        for (int i = 0; i < n; ++i){
            while (q > 0 && pattern[q] != text[i])
                q = next[q];
            if (pattern[q] == text[i])
                q = q + 1;
            if (q == m)
                return i - q + 1;
        }
        return -1;
    }

    void compute_prefix(const char *pattern, vector<int> &next){
        const int m = strlen(pattern);
        next[1] = 0;
        int k = 0;
        for (int q = 2; q <= m; ++q){                               //    q 表示 pattern 中前 [1,...,q] 位,对应的下标 [0,...,q-1]
            while (k > 0 && pattern[k] != pattern[q-1])     //    next[q] 表示前 q 位的最长前缀,不包括本身
                k = next[k];                               
            if (pattern[k] == pattern[q-1])
                k = k + 1;
            next[q] = k;
        }
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值