KMP类似暴力,但是不会和暴力完全一样,回溯到起点。
简单的说 假如 模板链字符串是: abcabcabcabd 寻找abcabd 在模板链出现的次数,并且输出该次数。
完全暴力过程:
假设 a【】为模板链,b【】为要查找的子序列。
先取b【】的首一直对应,然后a【】,b【】同时移动,当a【】,b【】不匹配的时候,b【】回到起点,a【】向后移动单位1。 这点很容易想到,我写出来是为了方便和后面的KMP算法作比较。
KMP过程:
假设仍然如上。
这个我们先要对b【】进行处理,假设做一个int的数组 next【】
b【】 a b c a b d
next【】 -1 0 0 0 1 2
匹配过程:
a【】 a b c a b c a b d >>>>>>>>>假设 在a中,查找b出现的次数,区间不交叉
简单说吧
前面和暴力相同
暴力得到结果为:a b c a b //此处还有d没匹配,下一步就是KMP的用处了
不同之处在于
a b c a b d(d处不对应)
下一次匹配对应的是
a b c a b d
(移动的位置跟next相同,d对应的next的值为2,所以b【】移动1+2的位置)
入门题: hdu 2087 点击打开链接
ac代码:
#include<cstdio>
#include<cstring>
char a[1010],b[1010];
int next[1010];
int lena,lenb;
void getnext() //做的第一步是获得next【】的值
{
int i=0,k=-1;
next[0]=-1;
while (i<lenb)
{
if (k==-1||b[i]==b[k])
{
i++;
k++;
next[i]=k;
}
else k=next[k];
}
}
int KMP()
{
getnext();
int i=0,j=0,cnt=0;
while (i<lena)
{
if (j==-1||a[i]==b[j])
{
i++;j++;
}
else j=next[j];
if (j==lenb)
{
cnt++;
j=0;
}
}
return cnt;
}
int main()
{
while(scanf("%s",a)!=EOF)
{
if (*a=='#')
break;
scanf("%s",b);
lena=strlen(a);
lenb=strlen(b);
printf ("%d
",KMP());
}
return 0;
}