[BZOJ3507][CQOI2014]通配符匹配(DP+Hash)
显然f[i][j]表示S匹配到第i个通配符,T匹配到第j个字符,是否可行。
一次一起转移两个通配符之间的所有字符,Hash判断。
稍微有点细节。常数极大卡时过排名倒数,可能是没自然溢出的原因。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 5 using namespace std; 6 7 const int N=200010,p1=133,p2=7393913; 8 bool f[20][N]; 9 char s1[N],s2[N]; 10 int n,m,T,tot,pos[20],h1[N],h2[N],pw[N]; 11 12 int main(){ 13 freopen("bzoj3507.in","r",stdin); 14 freopen("bzoj3507.out","w",stdout); 15 scanf("%s",s1+1); n=strlen(s1+1)+1; s1[n]='?'; 16 pw[0]=1; rep(i,1,n) pw[i]=1ll*pw[i-1]*p1%p2; 17 rep(i,1,n) h1[i]=(1ll*h1[i-1]*p1+s1[i])%p2; 18 rep(i,1,n) if (s1[i]=='?' || s1[i]=='*') pos[++tot]=i; 19 for (scanf("%d",&T); T--; ){ 20 scanf("%s",s2+1); m=strlen(s2+1)+1; s2[m]='#'; 21 rep(i,0,tot) rep(j,0,m) f[i][j]=0; f[0][0]=1; 22 rep(i,1,m) h2[i]=(1ll*h2[i-1]*p1+s2[i])%p2; 23 rep(i,0,tot) rep(j,0,m){ 24 if (s1[pos[i]]=='*') f[i][j]|=f[i][j-1]; 25 if (!f[i][j]) continue; 26 int l1=pos[i]+1,r1=pos[i+1]-1,l2=j+1,r2=j+(pos[i+1]-pos[i])-1; 27 if ((h1[r1]-1ll*h1[l1-1]*pw[r1-l1+1]%p2+p2)%p2==(h2[r2]-1ll*h2[l2-1]*pw[r2-l2+1]%p2+p2)%p2){ 28 if (s1[pos[i+1]]=='?') f[i+1][r2+1]|=f[i][j]; else f[i+1][r2]|=f[i][j]; 29 } 30 } 31 puts(f[tot][m] ? "YES" : "NO"); 32 } 33 return 0; 34 }