编程语言
首页 > 编程语言> > KMP子串查找算法

KMP子串查找算法

作者:互联网

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
那么部分匹配表怎么获得?
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
实现关键

  1. PMT[1]=0;(下标为0的元素匹配值为0)
  2. 从2个字符开始递推(从下标为1的字符开始递推)
  3. 假设PMT[n]=PMT[n-1]+1(最长共有元素的长度)
  4. 当假设不成立,PMT[n]在PMT[n-1]的基础上减小

在这里插入图片描述
部分匹配表是前辈找到的规律,不需要理解,会用就行!
获得部分匹配表函数如下:

int* make_pmt(const char* p)
{
    int len = strlen(p);
    int* ret = static_cast<int*>(malloc(sizeof(int)*len));

    if(ret != NULL)
    {
        int ll=0;
        ret[0]=0;
        for(int i=1;i<len;i++)
        {
            while( (ll>0) && (p[ll]!=p[i]))
            {
                ll = ret[ll-1];
            }
            if( p[ll] == p[i] )
            {
                ll++;
            }
            ret[i]=ll;
        }
    }

    return ret;
}

测试:

int main()
{
    int* pmt = make_pmt("abcdabd");

    for(int i=0;i<strlen("abcdabd");i++)
    {
        cout << i << ":" << pmt[i] << endl;
    }


    return 0;
}

在这里插入图片描述
和上面一致
在这里插入图片描述
KMP算法实现:

int kmp(const char* s,const char* p)//O(m+n)
{
    int ret = -1;
    int sl=strlen(s);
    int pl=strlen(p);
    int* pmt=make_pmt(p);
    if((pmt != NULL) && (0<pl) && (pl<=sl))
    {
        for(int i=0,j=0;i<sl;i++)
        {
            while((j>0) && (s[i] != p[j]))
            {
                j = pmt[j-1];
            }

            if(s[i] == p[j])
            {
                j++;
            }

            if(j == pl)//查找到
            {
                ret = i+1-pl;
                break;
            }
        }
    }
    free(pmt);
    return ret;
}

这你妈是人能写出来的?

在这里插入图片描述

标签:子串,pmt,int,ll,ret,char,查找,KMP,PMT
来源: https://blog.csdn.net/weixin_46258483/article/details/122515048