KMP算法:能在o(m+n)时间内匹配出连续相同的字符串
构造主要分成两个:1.模式串的预处理 2.文本串的朴素匹配
以ZQUOJ1317为例,主要看代码
/******
i: 0 1 2 3 4 5 6 7 8 9 10 11
p[i]:A B A B C A B A B A B C
f[i]:0 0 0 1 2 0 1 2 3 4 3 4
构造f[ i ],例如上图所示,f[ i ] 表示转移到p[ i ]的下标
用while ( j && p[i] != p[j] ) j = f[j]; 语句表示
******/
#include<stdio.h>
#include<string.h>
char t[100],p[100],f[100];
void getfail(char *p,char *f)
{
int m=strlen(p);
f[0]=0;f[1]=0; // 预处理
for(int i=1;i<m;i++)
{
int j=f[i];
while( j && p[i] != p[j] ) // 顺着失配边走,直到匹配为之
j=f[j];
// if(p[i]!=p[j]) // 若将while语句改掉答案则为RE,忽略掉一种情况
// j=0; // 既i=10的那种情况
f[i+1] = p[i] == p[j] ? j+1 : 0; // 匹配成功,加1
printf(" %d ",f[i]);
}
putchar('\n');
}
void find(char *t,char *p,char *f) // t是文本串,p是模版串,f是模版串里构造的next函数
{
int n=strlen(t),m=strlen(p);
getfail(p,f);
int j=0;
for(int i=0;i<n;i++) // 每次文本串i不移动,只移动模版串j。且移动的规则有f函数确定
{
while(j && p[j] != t[i]) //类似前面所述
j=f[j];
if(p[j]==t[i])
j++;
if(j==m)
{
printf("yes\n");
return ;
}
}
printf("no\n");
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
while(n)
{
scanf("%s",t);
scanf("%s",p);
find(t,p,f);
n--;
}
}
return 0;
}