题目链接:
http://poj.org/problem?id=3461
题目大意:
给两个字符串p和s,问p在s中出现了几次。
思路:
KMP模板题。
用KMP算法可以知道p是否在s 中出现,如果要知道出现几次,其实还是模拟匹配过程。如果匹配到一个成功的字符串,就继续看下去,同时j=next[j],相当于在第plen+1的地方字符串失配了,要重新给p定位。
代码:
#include<stdio.h>
#include<string.h>
int next[10005],t;
//优化过后的next 数组求法
void GetNextval(char* p, int next[])
{
int pLen = strlen(p);
next[0] = -1;
int k = -1;
int j = 0;
while (j < pLen )
{
//p[k]表示前缀,p[j]表示后缀
if (k == -1 || p[j] == p[k])
{
++j;
++k;
//较之前next数组求法,改动在下面4行
if (p[j] != p[k])
next[j] = k; //之前只有这一行
else
//因为不能出现p[j] = p[ next[j ]],所以当出现时需要继续递归,k = next[k] = next[next[k]]
next[j] = next[k];
}
else
{
k = next[k];
}
}
}
int KmpSearch(char* s, char* p)
{
int i = 0;
int j = 0;
int sLen = strlen(s);
int pLen = strlen(p);
GetNextval(p,next);
// for(i=0;i<=pLen;i++)
// printf("?%d\n",next[i]);
while (i < sLen && j < pLen)
{
//①如果j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++
if (j == -1 || s[i] == p[j])
{
i++;
j++;
}
else
{
//②如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j]
//next[j]即为j所对应的next值
j = next[j];
}
if (j == pLen)
{
j=next[j];t++;
}
}
}
char s1[10005],s2[1000005];
int main()
{
int T,i,j,k,l;
scanf("%d",&T);
while(T--)
{
t=0;
scanf("%s",s1);
scanf("%s",s2);
KmpSearch(s2,s1);
printf("%d\n",t);
}
}