KMP子串查找算法
作者:互联网
那么部分匹配表怎么获得?
实现关键
- PMT[1]=0;(下标为0的元素匹配值为0)
- 从2个字符开始递推(从下标为1的字符开始递推)
- 假设PMT[n]=PMT[n-1]+1(最长共有元素的长度)
- 当假设不成立,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