• 模板汇总——KMP & EX-KMP


    1. kmp

      相当于往前求出一段字符信息,使得 这段字符信息和前缀相等。

       

    void getnext(){
        int k = -1, j = 0;
        nx[0] = -1;
        while(j < m){
            if(k == -1 || b[j] == b[k]) nx[++j] = ++k;
            else k = nx[k];
        }
    }
    View Code

    例:

    T

    #include<iostream>
    using namespace std;
    int nx[10000+5], b[10000+5], a[1000000+5];
    int n, m;
    void getnext(){
        int k = -1, j = 0;
        nx[0] = -1;
        while(j < m){
            if(k == -1 || b[j] == b[k]) nx[++j] = ++k;
            else k = nx[k];
        }
    }
    int KMP()
    {
        int flag = -1;
        for(int i = 0, j = 0; i < n; i++){
            while(j > 0 && b[j] != a[i]) j = nx[j];
            if(a[i] == b[j]) j++;
            if(j == m)
            {
                return i - j + 2;
            }
        }
        return -1;
    }
    int main()
    {
        ios::sync_with_stdio(0);
        cin.tie(0);
        cout.tie(0);
        int t;
        cin >> t;
        while(t--){
            cin >> n >> m;
            for(int i = 0; i < n; i++) cin >> a[i];
            for(int i = 0; i < m; i++) cin >> b[i];
            getnext();
            cout << KMP() << endl;
        }
        return 0;
    }
    View Code

    2. ex-kmp 

      相当于往后求出一段信息,使得这段信息和前缀相等。

    int n, z[N];
    char s[N];
    void init(){
        z[0] = n;
        int j = 1, k;
        for(int i = 1; i < n; i = k){
            if(j < i) j = i;
            while(j < n && S[j] == S[j-i]) j++;
            z[i] = j-i;
            k = i+1;
            while(k + z[k-i] < j)
                z[k]=z[k-i],k++;
        }
    }
    View Code

    例:

    T:

    给出模板串A和子串B,长度分别为lenA和lenB,要求在线性时间内,对于每个A[i](1<=i<=lenA),求出A[i..lenA]与B的最长公共前缀长度。

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 2e6+100;
    
    char s[N], ss[N];
    int z[N];
    void init(int n){
        z[0] = n;
        int j = 1, k;
        for(int i = 1; i < n; i = k){
            if(j < i) j = i;
            while(j < n && s[j] == s[j-i]) j++;
            z[i] = j-i;
            k = i+1;
            while(k + z[k-i] < j)
                z[k]=z[k-i],k++;
        }
    }
    int Ac(){
        scanf("%s", ss);
        scanf("%s", s);
        int n = strlen(s), m = strlen(ss);
        s[n] = '@';
        strcpy(s+1+n, ss);
        init(n+m+1);
        for(int i = n+1; i <= n+m; ++i){
            printf("%d%c", z[i], " 
    "[i==n+m]);
        }
        return 0;
    }
    int main(){
        Ac();
        return 0;
    }
    View Code

      

  • 相关阅读:
    <audio> 标签简介
    <sessionState>
    为 IIS 7.0 配置 <system.webServer>
    Litepal 数据库操作框架的使用 (火)
    Oracle Study之-AIX6.1构建Oracle 10gR2 RAC(4)
    【iOS开发-55】图片轮播案例:scrollView的分页、滚动栏、利用代理控制定时器和Page Control以及多线程问题
    小白学react之网页获取微信用户信息
    HTML5游戏实战(1):50行代码实现正面跑酷游戏
    浮动、定位
    Tomcat7.0源代码分析——启动与停止服务原理
  • 原文地址:https://www.cnblogs.com/MingSD/p/10802603.html
Copyright © 2020-2023  润新知