[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 }
原文地址:https://www.cnblogs.com/HocRiser/p/10273037.html