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\n",i-lena+1);
                j=nxt[j];
            }
        }
        else j=nxt[j];
}
int main()
{
    scanf("%s\n%s",&b,&a);
    lena=strlen(a);
    lenb=strlen(b);
    getnxt();
    indexkmp();
    for(int i=1;i<=lena;i++)
    printf("%d ",nxt[i]);
    return 0;
}

 

posted @ 2020-06-16 17:15  Star_Cried  阅读(140)  评论(0编辑  收藏  举报