F03【模板】KMP 算法
F03【模板】KMP 算法——信息学竞赛算法_哔哩哔哩_bilibili
题目:给定文本串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; } 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; }
浙公网安备 33010602011771号