zoukankan      html  css  js  c++  java
  • KMP算法

    KMP 算法是 D.E.Knuth、J,H,Morris 和 V.R.Pratt 三位神人共同提出的,称之为 Knuth-Morria-Pratt 算法,简称 KMP 算法。

    问题求a字符串与b字符串中子串相同的串首位置。

    暴力就不说了,设a长m,b长n,每次枚举比对每个字符,复杂度O(nm)。

    KMP主要思想:如果一个字符串的子串与前缀相等,那么在查找时就可以直接将前缀跳至该子串的位置。复杂度O(n)。

    nxt[x]记录x位置字符在查询串中的跳转位置。

    eg:对于串abaabacac:

     a b a a b a c a c

    -1 0 0 1 1 2 3 0 1

    inline void getnxt()
    {
        int j=0,k=-1;
        nxt[0]=-1;
        while(j<s.length()-1)
        {
            if(k==-1||s[j]==s[k])nxt[++j]=++k;
            else k=nxt[k];
        }
    }

    查询时跳转即可。

    模拟一下就知道啦~

    全代码:

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    string s,t;
    int nxt[1000];
    inline void getnxt()
    {
        int j=0,k=-1;
        nxt[0]=-1;
        while(j<s.length()-1)
        {
            if(k==-1||s[j]==s[k])nxt[++j]=++k;
            else k=nxt[k];
        }
    }
    inline int indexkmp()
    {
        int i=0,j=0;
        while(i<s.length() and j<t.length())//如果比完了就退出来了 
            if(i==-1 or s[i]==t[j])i++,j++;
            else i=nxt[i];
        if(i>=s.length())return j-s.length();
        return -1;
    }
    int main()
    {
        std::ios::sync_with_stdio(false);
        cin>>s>>t;
        getnxt();
        cout<<indexkmp()+1;
        return 0;
    }

     例题

    洛谷P3375

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<cstring>
    using namespace std;
    const int maxn=1e6+5;
    int nxt[maxn];
    char a[maxn],b[maxn];
    int lena,lenb;
    inline void getnxt()
    {
        int k=-1,j=0;
        nxt[0]=-1;
        while(j<lena)
            if(k==-1 or a[k]==a[j])
            nxt[++j]=++k;
            else k=nxt[k];
    }
    inline void indexkmp()
    {
        int j=0,i=0;
        while(j<lena and i<lenb)
            if(j==-1 or a[j]==b[i]){
                i++,j++;
                if(j==lena){
                    printf("%d
    ",i-lena+1);
                    j=nxt[j];
                }
            }
            else j=nxt[j];
    }
    int main()
    {
        scanf("%s
    %s",&b,&a);
        lena=strlen(a);
        lenb=strlen(b);
        getnxt();
        indexkmp();
        for(int i=1;i<=lena;i++)
        printf("%d ",nxt[i]);
        return 0;
    }
  • 相关阅读:
    codeforces 363B
    hdu 1075 字典树
    D
    C A Simple Job
    Washing Plates 贪心
    HDU 4143 A Simple Problem 分解因式
    ACdream 1236 Burning Bridges 割边 + 去重边
    E. Beautiful Subarrays 字典树
    反素数 -- 数学
    Codeforces Beta Round #79 (Div. 1 Only) B. Buses 树状数组
  • 原文地址:https://www.cnblogs.com/BrotherHood/p/13138186.html
Copyright © 2011-2022 走看看