1 条题解

  • 0
    @ 2026-3-19 15:10:33

    F03【模板】KMP 算法

    题目:给定文本串a和模式串b,求模式串的前缀函数,求模式串在文本串中出现的所有位置。 模式串的前缀函数ne[i]:模式串前缀[1~i]的相等真前缀与真后缀的最大长度。 例 aabaabaaa:ne[1,2,3,4,5,6,7,8,9]={0,1,0,1,2,3,4,5,2}。 求模式串的前缀函数:双指针、预判、失配前跳、匹配后移、记录ne[i]。 让模式串匹配文本串:文本串的指针一直向前,模式串的指针前跳、后移。

    // KMP算法 O(|a|+|b|)
    #include<bits/stdc++.h>
    using namespace std;
    
    const int N=1000010;
    char a[N],b[N]; //a:文本串 b:模式串
    int ne[N]; //前缀函数ne[i]:模式串前缀[1~i]的相等真前缀与真后缀的最大长度
    
    int main(){
      cin>>a+1>>b+1;
      int la=strlen(a+1),lb=strlen(b+1);
      
      ne[1]=0;
      for(int i=2,j=0; i<=lb; i++){
        while(j && b[i]!=b[j+1]) j=ne[j]; //失配前跳
        if(b[i]==b[j+1]) j++;             //匹配后移
        ne[i]=j;                          //记录ne[i]
      }
      
      for(int i=1,j=0; i<=la; i++){
        while(j && a[i]!=b[j+1]) j=ne[j]; //失配前跳
        if(a[i]==b[j+1]) j++;             //匹配后移
        if(j==lb) printf("%d\n",i-lb+1);  //全配记录
      }
      
      for(int i=1;i<=lb;i++) printf("%d ",ne[i]);
      return 0;
    }
    
    
    // 哈希法 O(n)
    #include<bits/stdc++.h>
    using namespace std;
    
    typedef unsigned long long ull;
    const int N=1e6+5;
    const ull B=131;
    string s,t;
    int n,m;
    ull f[N],g[N],b[N];
    
    ull get1(int l,int r){
      return f[r]-f[l-1]*b[r-l+1];
    }
    ull get2(int l,int r){
      return g[r]-g[l-1]*b[r-l+1];
    }
    signed main(){
      ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
      cin>>s>>t;
      n=s.size(),m=t.size();
      s=" "+s; t=" "+t;
      b[0]=1;
      
      for(int i=1; i<N; ++i) b[i]=b[i-1]*B;
      for(int i=1; i<=n; ++i) f[i]=f[i-1]*B+s[i];
      for(int i=1; i<=m; ++i) g[i]=g[i-1]*B+t[i];
      for(int i=1; i<=n-m+1; ++i)
        if(get1(i,i+m-1)==g[m]) cout<<i<<'\n';
      
      cout<<0<<' ';
      for(int i=2,j=0; i<=m; ++i){
        while(j>=0 && get2(1,j+1)!=get2(i-j,i)) j--;
        j++;
        cout<<j<<' ';
      }
      return 0;
    }
    
    • 1

    信息

    ID
    9893
    时间
    1000ms
    内存
    512MiB
    难度
    5
    标签
    递交数
    36
    已通过
    15
    上传者