【题目链接】
https://www.lydsy.com/JudgeOnline/problem.php?id=4713
【题解】
首先考虑只有一个串时的做法,可以进行dp,记
表示从
的子树中任意一点出发到
能否匹配字符串的
位且
与
匹配。同时记
表示从
的子树中出发到
能否从后往前匹配字符串的
位并且
与
匹配。
显然有
&
及
&
及
那么我们在lca处统计答案。如果存在
且
那么就可以在以
为子树的字符树中匹配。
接下来我们把所有的询问串拼在一起,然后一起执行dp,并且通过bitset优化位运算的转移。就可以在合理的复杂度解决该题。
但是bzoj太慢了,所以可以把长度为1的询问串特判掉来优化常数。
时间复杂度
【代码】
/* - - - - - - - - - - - - - - -
User : VanishD
problem : [bzoj3713]
Points : bitset
- - - - - - - - - - - - - - - */
# include <bits/stdc++.h>
# define ll long long
# define inf 0x3f3f3f3f
# define N 30010
# define M 35010
using namespace std;
int read(){
int tmp = 0, fh = 1; char ch = getchar();
while (ch < '0' || ch > '9'){ if (ch == '-') fh = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9'){ tmp = tmp * 10 + ch - '0'; ch = getchar(); }
return tmp * fh;
}
struct Edge{
int data, next, vote;
}e[N * 2];
int head[N], place, n, m, sum, s[N], t[N], ch[M], belong[M], final[N], q[N], pl, pr, use[N], wi[200];
char st[N];
bitset <M> f[N], g[N], pre, bak, hav[27], ans, nowpre, nowbak;
void build(int u, int v, int c){
e[++place].data = v; e[place].next = head[u]; head[u] = place; e[place].vote = c;
}
void dfs(int x, int fa){
for (int ed = head[x]; ed != 0; ed = e[ed].next)
if (e[ed].data != fa)
dfs(e[ed].data, x);
q[++pr] = x;
}
void bfs(){
pl = 1, pr = n;
while (pl <= pr){
int x = q[pl++]; use[x] = true;
f[x] = pre; g[x] = bak;
for (int ed = head[x]; ed != 0; ed = e[ed].next)
if (use[e[ed].data] == true){
nowpre = (f[e[ed].data] << 1) & hav[e[ed].vote];
nowbak = (g[e[ed].data] >> 1) & hav[e[ed].vote];
ans = ans | (f[x] & (nowbak >> 1)) | (nowpre & (g[x] >> 1));
f[x] = f[x] | nowpre; g[x] = g[x] | nowbak;
}
}
}
int main(){
// freopen("bzoj4713.in", "r", stdin);
// freopen("bzoj4713.out", "w", stdout);
n = read();
for (int i = 1; i < n; i++){
int u = read(), v = read();
char c;
scanf("\n%c", &c); c -= 'a' - 1;
build(u, v, c); build(v, u, c);
wi[c] = true;
}
m = read();
sum = 0;
for (int i = 1; i <= m; i++){
s[i] = sum;
scanf("\n%s", st + 1);
int l = strlen(st + 1);
if (l == 1){
if (wi[st[1] - 'a' + 1] == true)
final[i] = true;
continue;
}
for (int j = 1; j <= l; j++)
ch[sum + j] = st[j] - 'a' + 1;
t[i] = sum + l + 1;
for (int j = s[i]; j < t[i]; j++) belong[j] = i;
sum = sum + l + 1;
}
for (int i = 1; i <= m; i++) pre.set(s[i]);
for (int i = 1; i <= m; i++) bak.set(t[i]);
for (int i = 1; i <= 26; i++)
for (int j = 0; j <= sum; j++)
if (ch[j] == i) hav[i].set(j);
pl = 1, pr = 0; dfs(1, 0);
bfs();
for (int i = 0; i <= sum; i++)
if (ans[i] == 1) final[belong[i]] = true;
for (int i = 1; i <= m; i++)
if (final[i] == true)
puts("YES"); else puts("NO");
return 0;
}