网上已经有巨佬写了一篇很详尽的KMP讲解了,我就放个传送门就行了。
这里我就写写我对KMP的理解就ok啦,可能写的很乱。。。
先粘代码:
void getnext(string a)
{
int len=a.size();
int k=-1;
int j=0;
nxt[0]=-1;
while(j<len)
{
if(k==-1||a[j]==a[k])
{
k++;
j++;
nxt[j]=k;
}
else
k=nxt[k];
}
}
理解了这个函数也就理解了如何递推(+递归?)求和后缀相同的最长前缀。精髓是k=next【k】。值得好好推敲。
下面是这篇博客的核心
int getans(string s,string a)
{
int i=0;
int j=0;
int slen=s.size();
int alen=a.size();
while(j<slen&&i<alen)
{
if(i==-1||a[i]==s[j])
{
i++;
j++;
}
else
i=nxt[i];
}
if(i==alen)
return j-i;
else
return -1;
}
之前我想着next数组求完了之后就可以为所欲为了 (不就是个比对吗?) 随便写写就写成了下面的这样
void getans(string s,string p)
{
int slen=s.size();
int plen=p.size();
int i=0;
int j=0;
while(j<slen&&i<plen)
{
i=0;
while(s[j]==p[i]&&i<plen&&j<slen)
{
i++;
j++;
}
if(j==slen)
break;
j-=Next[i];
}
if(i==plen)
{
ans++;
return ;
}
}
在洛谷上交了个板子发现没什么问题,回来对比一下大佬的板子发现出入很大。当时没细想,现在再看看终于意识到自己和大佬的差距了。
先不说两层while有多容易翻车,在算法的效率上都错了十万八千里。大佬的代码思想是母串对已经搜过的部分不再重复搜索(小常数*母串长度的复杂度),我的想法是回到上一个可能匹配成功的地方(对暴力的简单优化)。
举个栗子:
母串: asdasdasdasdc
模板串: asdasdc
跑一下就发现问题了,细节决定成败啊。·