zoukankan      html  css  js  c++  java
  • KMP 理解

    例题

    以字符串 ABABACA 为例

    a
    前缀:
    后缀:

    结果为0

    ab
    前缀:a
    后缀: b

    结果为0

    aba
    前缀:a ab
    后缀: ba a

    结果为1,此时 i=2,j=1

    abab
    前缀:a ab aba
    后缀: bab ab b

    结果为2,此时 i=3,j=2

    ababa
    前缀:a ab aba abab
    后缀: baba aba ba a

    结果为3,此时 i=4,j=3

    ababac
    前缀:a ab aba abab ababac
    后缀: babac abac bac ac c

    结果为0,此时 i=5,j=3,1,0

    ababaca
    前缀:a ab aba abab ababac ababaca
    后缀: babaca abaca baca bac ac c

    结果为1,此时 i=6,j=0

    next数组结果:
    0 0 0 1 2 3 0 1

    总结

    以i为尾,往前数对应值,即是相等的,前提是相等的情况下(废话!);

    前缀:要第一个字母,不要最后一个字母;
    后缀:不要第一个字母,要最后一个字母;

    至于i+1,因为计算的是前缀和后缀的重合的值的长度,所以还需要加上1;

    最重要的是
    j = next[i - 1],比如说现在在 i 位置上不匹配,为了避免重复匹配,不想浪费之前 0 到 i-1 的匹配长度,也就是说要找以 0 开头,i-1 结尾的匹配的子串,就是说找字符串上 i-1 位置的重合长度,因为next数组存储的是前缀和后缀的重合长度,所以还需要 i-1-1,也就是找next[i-1-1]的值,此时我们再比较字符串上 i 和 j 位置的字符是否相等;

    如果相等 j 就尽管移动,代表重合的长度,也就是说到了该位置不匹配,只需要向前移动next数组中对应的长度。

    enter image description here
    enter image description here

    贴上代码:

    #include <iostream>
    #include <string>
    #include <vector>
    using namespace std;
    
    vector<int> getNext(string str) {
        int len = str.size();
        int j = 0;
        
        vector<int>next(len + 1);
        next[0] = next[1] = 0;
        
        // j表明相同的个数
        for (int i = 1; i < len; i++) {
            while (j > 0 && str[i] != str[j]) {
                j = next[j];
            }
            // 相同的个数
            if (str[i] == str[j]) {
                j++;
            }
            next[i+1] = j;
        }
        
        return next;
    }
    
    // 另一种写法
    //    vector<int> getNext2(string str) {
    //        int j = 0;
    //        int i = 1;
    //        
    //        vector<int> next(str.size());
    //        next[0] = 0; // 必须是0
    //        
    //        while (i < str.size()) {
    //            if (str[i] == str[j]) {
    //                j++;
    //                next[i] = j;
    //                i++;
    //            }
    //            else {
    //                if (j != 0) {
    //                    j = next[j - 1];
    //                }
    //                else { // j 为 0
    //                    next[i] = 0;
    //                    i++;
    //                }
    //            }
    //        }
    //        
    //        return next;
    //        
    //    }
    
    
    int search(string original, string find, vector<int> next) {
        int i = 0, j = 0;
        for (i = 0; i < original.length(); ++i) {
            while (j > 0 && original[i] != find[j]) {
                j = next[j];
            }
            if (original[i] == find[j])
                ++j;
            if (j == find.size()) {
                return i - j + 1;
            }
        }
        
        return -1;
    }
    
    int main(int argc, const char * argv[]) {
        string o = "ABABACAAC";
        string f = "ABABACA";
        
        vector<int> next = getNext(f);
        // next
        int i = 1;
        while (i < next.size()) {
            cout << "next " << next[i] << endl;
            i++;
        }
        
        //search
        int result = search(o, f, next);
        cout << "result " << result << endl;
        
        return 0;
    }
    
    
  • 相关阅读:
    最近很火的GAN应用
    pose项目里我遇到的问题
    pose的初体验
    Ubuntu 移动硬盘不能用
    深度学习中参数量与计算量的理解
    GAN的流程-cyclegan为例
    The version of SOS does not match the version of CLR you are debugging
    mnist 手写数字识别
    计算模型-图、数据模型-张量、运算模型-会话
    tensorflow环境安装
  • 原文地址:https://www.cnblogs.com/George1994/p/6346778.html
Copyright © 2011-2022 走看看