KMP算法刚开始学起来有点抽象的,但是理解了之后还是非常清晰的。网上关于KMP算法的讲解非常多也非常详细的,就不过多赘述,下面就仅给出我的模板代码以及做题时踩过的坑和解题思路。
1 模板代码
void GetNext()
{
Next[1] = 0;
int j = 0;
for(int i=1; i<strlen(b+1); i++)
{
while(j>0 && b[j+1]!=b[i+1])
j = Next[j];
if(b[j+1]==b[i+1])
j++;
Next[i+1] = j;
}
}
int main()
{
memset(Next, 0, sizeof(Next));
GetNext();
int ans = 0, j = 0;
for(int i=0; i<strlen(a+1); i++)
{
while(j>0 && b[j+1]!=a[i+1])
j = p[j];
if(b[j+1]==a[i+1])
j++;
if(j==strlen(b+1))
{
ans++;
j = 0; //不可重叠
// j = Next[j]; //可重叠
}
}
}
2 Example
2.1 N 剪花布条
#include<bits/stdc++.h>
using namespace std;
char a[1010],b[1010];
int p[1010];
void pre()
{
p[1] = 0;
int j = 0;
for(int i=1; i<strlen(b+1); i++)
{
while(j>0 && b[j+1]!=b[i+1])
j = p[j];
if(b[j+1]==b[i+1])
j++;
p[i+1] = j;
}
}
int main()
{
while(scanf("%s",a+1)&& a[1] != '#'&&scanf("%s",b+1))
{
memset(p,0,sizeof(p));
pre();
int ans = 0, j = 0;
for(int i=0; i<strlen(a+1); i++)
{
while(j>0 && b[j+1]!=a[i+1])
j = p[j];
if(b[j+1]==a[i+1])
j++;
if(j==strlen(b+1))
{
ans++;
j = 0; //不可重复匹配
}
}
for(int i=1; i<=strlen(b+1); i++)
printf("%d ", p[i]);
printf("\n");
printf("%d\n", ans);
}
return 0;
}
2.2 O Simpsons’ Hidden Talents
解题思路:把s1串和s2串合并在一起,通过Next数组记录前缀和后缀公共元素的最大长度。
#include<bits/stdc++.h>
using namespace std;
int Next[100020];
char s[100020], p[100020];
int slen, plen, ulen, ans;
void GetNext()
{
Next[1] = 0;
int j = 0;
for(int i=1; i<=ulen; i++)
{
while(j>0 && s[j+1]!=s[i+1])
j = Next[j];
if(s[j+1]==s[i+1])
j++;
Next[i+1] = j;
}
}
int main()
{
int cnt;
while(scanf("%s %s", s+1, p+1) != EOF)
{
slen = strlen(s+1);
plen = strlen(p+1);
for(int i=slen+1; i<=slen+plen; i++)
s[i] = p[i-slen];
ulen = slen + plen;
GetNext();
ans = Next[ulen];
if(ans==0)
printf("0\n");
else
{
for(int i=1; i<=ans; i++)
printf("%c", s[i]);
printf(" %d\n", ans);
}
}
}
问题1:
abemda
bem
若只是简单的输出Next[strlen(s1+s2)]数组,则以上样例是无法通过的,所以需要在上述代码基础上添加对Next[strlen(s1+s2)]、strlen(s1)、strlen(s2)大小的判断,并通过不断的递归找到不会超过s1、s2长度的前缀和后缀公共元素的最大长度。
while(ans > min(slen, plen))
ans = Next[ans];
问题2(这只是一个非常小白的问题):
之前提交的代码没有使用slen, plen, ulen...这些变量,全部使用strlen()直接计算的,导致代码超时。所以还是要记得设变量啊。。