KMP算法

KMP是一种字符串模式匹配算法,在目标串中查找模式串的方法。

朴素查找方法在遇到目标串字串具备大量重复前缀且和模式串大部分吻合,其时间复杂度就会衰退为o(N*M),严格来说是o((N-M+1)*M)。

因此,在数据量很大的时候我们需要一种线性复杂度的算法。

KMP的优势是通过next数组记录了模式串从0~i-1位之前的最长重复前后缀的长度,当出现失配情况时,不像朴素算法那样返回模式串的初始位置,而是根据模式串失配之前的位匹配成功的特性,返回失配位前最长重复前缀长度在模式串的位置。

获取nex数组:

void getNex(unsigned long int len)//数组名nex 字符串名b 传入参数b.len
{
    nex[0]=-1;
    int i=-1,pos=0;
    while(pos<len)
    {
        if(i!=-1&&b[i]!=b[pos])
            i=nex[i];
        else
        {
            i++,pos++;
            nex[pos]=i;
        }
    }
}

kmp函数:

int kmp(int lena,int lenb,int st)//文本长度、模式串长度、文本起始位置
{
    int i=st,j=0;
    while(i<lena&&j<lenb)//千万不要用unsigned定义lenb,正负比较会出错
    {
        if(j==-1||a[i]==b[j])
            i++,j++;
        else
            j=nex[j];
    }
    if(j==lenb)
        return i;
    return -1;
}

统计匹配次数(可重叠)

int kmp(int la,int lb)
{
    int pa=0,pb=0;
    int cnt=0;
li:
    while(pa<la&&pb<lb)
    {
        if(pb!=-1&&a[pa]!=b[pb])
            pb=nex[pb];
        else
            pa++,pb++;
    }
    if(pb==lb)
    {
        cnt++,pb=nex[pb];
        goto li;
    }
    else
        return cnt;
}

统计匹配次数(不可重叠)

int kmp(int lena,int lenb,int st)//文本长度、模式串长度、文本起始位置
{
    int i=st,j=0,sum=0;
    while(i<lena&&j<lenb)//千万不要用unsigned定义lenb,正负比较会出错
    {
        if(j==-1||a[i]==b[j])
        {
            i++,j++;
            if(j==lenb)
                sum++,j=0;
        }
        else
            j=nex[j];
    }
    return sum;
}

若上文出现任何错误请及时指出,感谢!

原文地址:https://www.cnblogs.com/LukeStepByStep/p/5774910.html