【題解】2021HDU多校第三場 HDU6975 Forgiving matching
阿新 • • 發佈:2021-07-29
2021HDU多校第三場 HDU6975 Forgiving matching
題意
給一個串\(A\),和串\(B\)(均僅含字元'1'-'9'或萬用字元'*'),其中萬用字元可以匹配任意字元,分別求出最多容許\(k\)個字元失配的情況下(\(0\le k\le m\)),有多少個\(A\)的子串和\(B\)匹配。
\(1\le |B|\le |A|\le 2\times 10^5,\sum|A|\le 10^6\)
題解
做法類似於Fuzzy search。兩個字元匹配當且僅當它們字元相等,或者至少有一個是萬用字元。由於需要求出\(A\)中每個長度為\(m\)的子串有多少個位置與\(B\)串匹配,我們可以對每個字元分開處理.對於數字字元\(c\)
#include <bits/stdc++.h> typedef double db; typedef long long ll; using namespace std; const double pi=acos(-1.0); const int N=2300005; int r[N]; struct cpl{ db x,y; cpl operator +(const cpl & bb)const{return (cpl){x+bb.x,y+bb.y};} cpl operator -(const cpl & bb)const{return (cpl){x-bb.x,y-bb.y};} cpl operator *(const cpl & bb)const{return (cpl){x*bb.x-y*bb.y,x*bb.y+y*bb.x};} cpl operator /(const db &bb)const{return (cpl){x/bb,y/bb};} }a[N],b[N]; void fft(cpl *a,int lim,int typ){ for(int i=0;i<=lim;i++)if(i<r[i])swap(a[i],a[r[i]]); for(int mid=1;mid<lim;mid<<=1){ cpl w1=(cpl){cos(pi/mid),typ*sin(pi/mid)}; for(int R=mid<<1,j=0;j<lim;j+=R){ cpl w=(cpl){1,0}; for(int i=0;i<mid;i++,w=w*w1){ cpl y=a[i+j+mid]*w; a[i+j+mid]=a[i+j]-y;a[i+j]=a[i+j]+y; } } } if(typ==-1){ for(int i=0;i<=lim;i++)a[i].x/=lim; for(int i=0;i<=lim;i++)a[i].y/=lim; } } int lim=0,l=0,n,m; int f[N],s1[N],s2[N],ans[N]; void f1(){ string A,B; cin>>n>>m; cin>>A>>B; s1[0]=(A[0]=='*');s2[0]=(B[0]=='*'); for(int i=0;i<=n;i++){f[i]=0;ans[i]=0;} for(int i=1;i<n;i++){s1[i]=s1[i-1]+(A[i]=='*');} for(int i=1;i<m;i++){s2[i]=s2[i-1]+(B[i]=='*');ans[i]=0;} lim=1;l=0;while(lim<=(n+m)){lim<<=1;++l;} for(int i=0;i<lim;i++)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1)); for(int o=0;o<10;o++){ char c='0'+o; for(int i=0;i<=lim;i++){a[i].x=a[i].y=0;b[i].x=b[i].y=0;} for(int i=0;i<n;i++){ if(A[i]==c){a[i].x=1;} } for(int i=0;i<m;i++){ if(B[i]==c){a[m-1-i].y=1;} } fft(a,lim,1); for(int i=0;i<=lim;i++){a[i]=a[i]*a[i];} fft(a,lim,-1); for(int i=m-1;i<n;i++){f[i]+=(int)(0.5+a[i].y/2.0);} } { //處理萬用字元 char c='*'; for(int i=0;i<=lim;i++){a[i].x=a[i].y=0;b[i].x=b[i].y=0;} for(int i=0;i<n;i++){ if(A[i]==c){a[i].x=1;} } for(int i=0;i<m;i++){ if(B[i]==c){a[m-1-i].y=1;} } fft(a,lim,1); for(int i=0;i<=lim;i++){a[i]=a[i]*a[i];} fft(a,lim,-1); int ns=s2[m-1]; for(int i=m-1;i<n;i++){ if(i==m-1){ f[i]+=s1[i]+ns-(int)(0.5+a[i].y/2.0); } else{ f[i]+=s1[i]-s1[i-m]+ns-(int)(0.5+a[i].y/2.0); } } } for(int i=m-1;i<n;i++){ ans[m-f[i]]++; } for(int i=1;i<=m;i++){ ans[i]+=ans[i-1]; } for(int i=0;i<=m;i++){ cout<<ans[i]<<"\n"; } } int main(){ std::ios::sync_with_stdio(false); cin.tie(nullptr); int t;cin>>t; while(t--) f1(); return 0; }