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;
    }
    
    
  • 相关阅读:
    Java Spring Boot VS .NetCore (十) Java Interceptor vs .NetCore Interceptor
    Java Spring Boot VS .NetCore (九) Spring Security vs .NetCore Security
    IdentityServer4 And AspNetCore.Identity Get AccessToken 问题
    Java Spring Boot VS .NetCore (八) Java 注解 vs .NetCore Attribute
    Java Spring Boot VS .NetCore (七) 配置文件
    Java Spring Boot VS .NetCore (六) UI thymeleaf vs cshtml
    Java Spring Boot VS .NetCore (五)MyBatis vs EFCore
    Java Spring Boot VS .NetCore (四)数据库操作 Spring Data JPA vs EFCore
    Java Spring Boot VS .NetCore (三)Ioc容器处理
    Java Spring Boot VS .NetCore (二)实现一个过滤器Filter
  • 原文地址:https://www.cnblogs.com/George1994/p/6346778.html
Copyright © 2011-2022 走看看