题目链接: poj 3461
题目大意: 给出主串和模式串,求模式串在主串中出现的次数(部分可以重合)
解题思路: KMP从主串的第一个字符开始匹配
开始是匹配成功就立刻退出,再次从上次退出的下一个字符开始匹配,TLE...
利用上next[ ]数组的含义,每次不全部退出,而是退出部分j=next[ j ]
代码:
//Final Kmp,给出模式串和主串,求模式串在主串中出现的次数(可以部分重叠)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 10010
int Tlen,TTlen,End,next[MAX];
char ch[MAX*100],chT[MAX];
void Get_next()
{
int i=0,j=-1;
next[0]=-1;
while(i<=Tlen)
{
if(j==-1||chT[i]==chT[j])
{
i++; j++;
next[i]=j;
}
else
j=next[j];
}
}
int Kmp(int u)
{
int i=u-1,j=-1,m=0; //字符串从0开始存储的
while(i<=TTlen)
{
if(j==-1||ch[i]==chT[j])
{
i++; j++;
}
else
j=next[j];
if(j>=Tlen) //**注意这里要j--,i++,因为上面匹配成功了i和j的值加多了1
{
m++;
j--; i--;
j=next[j]; //返回
}
}
return m;
}
int main()
{
int n,m,k,i;
scanf("%d",&n);
while(n--)
{
scanf("%s%s",chT,ch);
memset(next,0,sizeof(next));
Tlen=strlen(chT);
TTlen=strlen(ch);
Get_next();
k=Kmp(0); //Kmp从第一个字符开始匹配
printf("%d\n",k);
}
return 0;
}