思路:就是DP+字符串hash,网上还有一些用ac自动机写的
#include <bits/stdc++.h>
using namespace std;
#define ul unsigned long long
const ul p = 666, N = 100000;
ul sx[N + 5], sy[N + 5], s[N + 5];
int len, lenn, w[12], num, t;
char ch[N + 5], cc[N + 5];
bool f[12][N + 5]; // f[i][j] 表示第i个通配符匹配以j结尾的字符(串)
int main() {
s[0] = 1;
for (int i = 1; i <= N; i++) // s数组存次方
s[i] = s[i - 1] * p;
scanf("%s", ch + 1);
len = strlen(ch + 1);
ch[++len] = '?'; //在末尾加上一个 ?处理结尾部分
for (int i = 1; i <= len; i++) {
sx[i] = sx[i - 1] * p + ch[i]; //预处理出 hash 前缀和
if (ch[i] == '*' or ch[i] == '?')
w[++num] = i; //记录通配符的下标
}
scanf("%d", &t);
while (t--) {
scanf("%s", cc + 1);
lenn = strlen(cc + 1);
cc[++lenn] = '!'; //在末尾加上一个 字符处理结尾部分
for (int i = 1; i <= lenn; i++)
sy[i] = sy[i - 1] * p + cc[i]; //预处理出 hash 前缀和
memset(f, 0, sizeof(f));
f[0][0] = 1; //初始化
for (int i = 0; i <= num; i++) { //枚举每一个通配符
if (ch[w[i]] == '*')
for (int j = 1; j <= lenn; j++)
f[i][j] |= f[i][j - 1]; //是 * 特殊处理
for (int j = 0; j <= lenn; j++) { //枚举每一个被匹配的字符串字符
if (!f[i][j]) //如果i对应字符没有可以匹配的字符就跳过
continue;
int la = w[i] + 1, ra = w[i + 1] - 1, lb = j + 1,
rb =
j + w[i + 1] - w[i] -
1; //计算出两段的左右端点(所以在字符串的最末尾都要加一个符号方便判断
if (sx[ra] - sx[la - 1] * s[ra - la + 1] ==
sy[rb] - sy[lb - 1] * s[rb - lb + 1]) { //判断两段是否相同
if (ch[w[i + 1]] == '?')
f[i + 1][rb + 1] = 1;
else
f[i + 1][rb] =
1; //注意:如果是 *
//,应将f[i+1][rb]赋值为1而不是f[i+1][rb+1]
//(*可以匹配长度为0的字符串)
}
}
}
if (f[num][lenn])
puts("YES");
else
puts("NO");
}
return 0;
}