题解:
维护26个字母的哈希,差值形如
Gk
G
k
,判断
k
k
<script type="math/tex" id="MathJax-Element-20">k</script>是否只有一个即可。
代码:
#include <bits/stdc++.h>
#include <tr1/unordered_map>
using namespace std;
typedef long long LL;
typedef pair <int,int> pii;
typedef unsigned long long ULL;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
const int N=1e5+50, LIM=20;
const ULL base=31, invb=17256631552825064415;
int n,fa[LIM][N], dep[N], anc[26];
ULL sum[26], pw[N], iw[N];
vector <pii> edge[N];
tr1::unordered_map <ULL,int> S;
inline int up(int x,int d) {
for(int i=LIM-1;~i;i--)
if(d&(1<<i)) x=fa[i][x];
return x;
}
inline int lca(int x,int y) {
if(dep[x]<dep[y]) swap(x,y);
x=up(x,dep[x]-dep[y]);
if(x==y) return x;
for(int i=LIM-1;~i;i--)
if(fa[i][x]!=fa[i][y]) x=fa[i][x], y=fa[i][y];
return fa[0][x];
}
struct Tree {
ULL hu[N],hd[N];
inline void dfs(int x,int f) {
hu[x]=hu[f]*base+hu[x];
hd[x]=hd[f]+hd[x]*pw[dep[x]];
for(auto v:edge[x]) if(v.first!=f) dfs(v.first,x);
}
inline void init() {dfs(1,0);}
inline ULL gu(int x,int f) {
return hu[x]-hu[f]*pw[dep[x]-dep[f]];
}
inline ULL gv(int x,int f) {
return (hd[x]-hd[f])*iw[dep[f]+1];
}
inline ULL gv(int u,int v,int l) {
return gu(u,l)+gv(v,l)*pw[dep[u]-dep[l]];
}
}tr[26];
inline int ga(int x) {return (anc[x]==x) ? x : (anc[x]=ga(anc[x]));}
inline void dfs(int x,int f) {
dep[x]=dep[f]+1; fa[0][x]=f;
for(int i=1;i<LIM;i++) fa[i][x]=fa[i-1][fa[i-1][x]];
for(auto v:edge[x]) {
if(v.first==f) continue;
tr[v.second].hu[v.first]=1;
tr[v.second].hd[v.first]=1;
dfs(v.first,x);
}
}
inline void hash_init() {
pw[0]=1; iw[0]=1;
for(int i=1;i<=n;i++) pw[i]=pw[i-1]*base,iw[i]=iw[i-1]*invb;
for(int i=0;i<=n;i++) S[pw[i]]=i, S[-pw[i]]=i;
dfs(1,0);
for(int i=0;i<26;i++) tr[i].init();
}
int main() {
n=rd();
for(int i=1;i<n;i++) {
int x=rd(), y=rd(), w=nc()-'a';
edge[x].push_back(make_pair(y,w));
edge[y].push_back(make_pair(x,w));
}
hash_init();
for(int i=rd();i;i--) {
int k=rd(), x1=rd(), y1=rd(), x2=rd(), y2=rd();
for(int j=0;j<26;j++) anc[j]=j, sum[j]=0;
for(int j=1;j<=k;j++) {
char ch=nc();
while(isspace(ch)) ch=nc();
anc[ga(ch-'a')]=ga(nc()-'a');
}
int l1=lca(x1,y1), l2=lca(x2,y2);
for(int j=0;j<26;j++)
sum[ga(j)]+=tr[j].gv(x1,y1,l1), sum[ga(j)]-=tr[j].gv(x2,y2,l2);
int fir=-1, bz=1;
for(int j=0;j<26&&bz;++j) if(ga(j)==j) {
if(!sum[j]) continue;
if(S.count(sum[j])) {
if(!~fir || S[sum[j]]==fir) fir=S[sum[j]];
else bz=0;
} else bz=0;
}
puts(bz?"YES":"NO");
}
}