考前记忆模板。
我们回忆一下 $next$ 数组的含义:
$next[i]$ 表示在 $[1,i-1]$ 内,前缀与后缀相同的部分最长是多长。可以理解为,若第 $i$ 位失配了,至少要往前跳多少步,才可能重新匹配得上。
于是对于匹配串,预处理出它的 $next$ 数组,然后对文本串逐位匹配即可。
#include
#define maxn 1000001
char p[maxn],t[maxn];
int next[maxn],n,m;
int main(){
scanf("%s%s",p+1,t+1);
n=strlen(p+1),m=strlen(t+1);
for (register int i=2,j=0;i<=m;++i){
while(j&&t[j+1]!=t[i]) j=next[j];//失配则回到上个匹配的位置;
if (t[j+1]==t[i]) j++;//匹配就继续向后
next[i]=j;
}
for (register int i=1,j=0;i<=n;++i){
while(j&&p[i]!=t[j+1]) j=next[j];//失配则回到上个匹配的位置;
if (t[j+1]==p[i]) j++;//匹配就继续向后
if (j==m) printf("%d\n",i-m+1),j=next[j];//完整匹配则输出
}
for (register int i=1;i<=m;++i)
printf("%d ",next[i]);
return 0;
}
后记 不知道为什么我内心一直觉得 NOIp 会考这个算法。。。说不定被我奶中了呢。。。