P3375 【模板】KMP字符串匹配

https://www.luogu.com.cn/problem/P3375


思路:

以前看着有一点迷糊。现在看看kmp的核心就是一个处理最大公共前后缀,匹配失败的时候直接优化。定义D[i]:0~i的一共i+1个字母的最大公共前后缀。处理的p和t匹配的时候直接用d就能优化,预处理出d[i]就是错开一位让p串和自身匹配,当然由于匹配到i位置,前i-1的D[0~i-1]都处理好了,所以这个匹配也是直接匹配失败跳转的。

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=1e6+100;
typedef int LL;
inline LL read(){LL x=0,f=1;char ch=getchar();	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;}
LL d[maxn];
char s1[maxn],s2[maxn];
/*d[i]:p[0]~p[i]共计i+1个字符的最大公共前后缀*/
void pre(const char s[],LL np){
     for(LL i=0;i<=np+10;i++) d[i]=0;
     LL i=1;LL j=0;
     while(i<np){
        if(s[i]==s[j]) d[i++]=++j;
        else{
            if(j>0) j=d[j-1];
            else i++;
        }
     }
}
void kmp(const char t[],const char p[]){
     LL nt=strlen(t);
     LL np=strlen(p);///预处理border
     pre(p,np);
     LL i=0;LL j=0;
     while(i<nt){
        if(p[j]==t[i]){
            i++;j++;
            if(j==np){
                printf("%d\n",i-j+1);
                j=d[np-1];
            }
        }
        else{
            if(j>0) j=d[j-1];
            else i++;
        }
     }
}
int main(void){
   scanf("%s%s",s1,s2);
   kmp(s1,s2);
   LL sn=strlen(s2);
   for(LL i=0;i<sn;i++) printf("%d ",d[i]);
   return 0;
}

 

上一篇:漫画:什么是KMP算法?


下一篇:KMP算法在圆周率中查找生日