[BZOJ3507][Cqoi2014]通配符匹配

Time Limit: 10 Sec
Memory Limit: 128 MB

Description

Output

Sample Input

*aca?ctc
6
acaacatctc
acatctc
aacacatctc
aggggcaacacctc
aggggcaacatctc
aggggcaacctct


Sample Output

YES
YES
YES
YES
YES
NO


HINT

1 &lt; = n &lt; = 100 1 &lt;=n&lt;=100

DP
p [ i ] p[i] 表示第 i i 个通配符的位置
f [ i ] [ j ] f[i][j] 表示拥有第 i i 个通配符可否和前 j j 个字符匹配。

for(int i=1;i<=len;i++)if(f[i][j-1]==1)f[i][j]=1;


（如果f[i][j]==1并且 s [ j + 1 ] s[j+1] 后面顺延 i i i + 1 i+1 之间的距离的字符和第 i i i + 1 i+1 个通配符之间的字符刚刚好相同）

if(rs[p[i+1]]=='?'){
f[i+1][j+(p[i+1]-1)-(p[i]+1)+1+1]=1;
}
else{
f[i+1][j+(p[i+1]-1)-(p[i]+1)+1]=1;
}


f [ i ] [ j ] f[i][j] 来更新其所能影响到的区间。

#include<bits/stdc++.h>
#define LiangJiaJun main
#define MOD 19991227
#define ll long long
#define uint unsigned int
using namespace std;
char s[100004],rs[100004];
int p[14],cnt;
uint hs[100004],hsa[100004],poo[100004];
int f[14][100004];

bool check(int L1,int R1,int L2,int R2){
int N1,N2;
if(R1>=L1)N1=(hs[R1]-((hs[L1-1]*poo[R1-L1+1])));
else N1=-1;
if(R2>=L2)N2=(hsa[R2]-((hsa[L2-1]*poo[R2-L2+1])));
else N2=-1;
return (N1==N2);
}
int n;
int w33ha(){
memset(f,0,sizeof(f));
cnt=0;
scanf("%d",&n);
hsa[0]=0;
int lrs=strlen(rs+1);
for(int i=1;i<=lrs;i++){
if(rs[i]=='*'||rs[i]=='?'){
p[++cnt]=i;
}
}
p[++cnt]=lrs+1;
rs[++lrs]='?';
for(int i=1;i<=lrs;i++){
int now;
if('a'<=rs[i]&&rs[i]<='z')now=rs[i]-'a';
if(rs[i]=='*')now=26;
if(rs[i]=='?')now=27;
hsa[i]=(hsa[i-1]*28+now);
}
for(int CASE=1;CASE<=n;CASE++){
scanf("%s",s+1);
int l=strlen(s+1);
for(int i=0;i<=cnt;i++)
for(int j=0;j<=l+1;j++)
f[i][j]=0;
hs[0]=0;
for(int i=1;i<=l;i++){
int now;
if('a'<=s[i]&&s[i]<='z')now=s[i]-'a';
if(s[i]=='*')now=26;
if(s[i]=='?')now=27;
hs[i]=(hs[i-1]*28+now);
}
s[++l]='_';
f[0][0]=1;
for(int i=0;i<cnt;i++){
if(rs[p[i]]=='*'){
for(int j=1;j<=l;j++)if(f[i][j-1])f[i][j]=1;
}
for(int j=0;j<=l;j++){
if(!f[i][j])continue;
if(check(j+1,j+(p[i+1]-1)-(p[i]+1)+1,p[i]+1,p[i+1]-1)){
if(rs[p[i+1]]=='?'){
f[i+1][j+(p[i+1]-1)-(p[i]+1)+1+1]=1;
}
else{
f[i+1][j+(p[i+1]-1)-(p[i]+1)+1]=1;
}
}
}
}
if(f[cnt][l])puts("YES");
else puts("NO");
}
return 0;
}
int LiangJiaJun(){
poo[0]=1;
for(int i=1;i<=100000;i++)poo[i]=(poo[i-1]*28);
while(scanf("%s",rs+1)!=EOF)w33ha();
return 0;
}


06-28 182

01-09 413
03-06 112
08-18 30
03-30 127
04-20 295
11-18 71
04-13 4369
06-18 36
11-10 843
10-03 68
06-19 32
03-18 2028
05-13 815