#include <bits/stdc++.h>
using namespace std;
vector<int> compute_z(const string& s) {
  int n = int(s.size());
  vector<int> z(n);
  z[0] = n;
  int l = 0, r = 0;
  for (int i = 1; i < n; i++) {
    int cur = (i >= r ? 0 : min(r - i, z[i - l]));
    while (i + cur < n && s[cur] == s[i + cur]) {
      cur++;
    }
    z[i] = cur;
    if (i + cur > r) {
      l = i;
      r = i + cur;
    }
  }
  return z;
}
int match(const string& a, string b) {
  int n = int(b.size());
  b.append(1, '#');
  b.append(a);
  vector<int> z = compute_z(b);
  assert(z[n] == 0);
  int ans = 0;
  for (int i = n + 1; i < int(b.size()); i++) {
    ans += (z[i] == n);
  }
  return ans;
}
const int MAXN = 1.1e5;
const int MAXM = 1.1e5;
const int B = 5000;
const int MAXL = 110 * B;
int N, M;
vector<pair<int, char> > adj[MAXN];
char pc[MAXN];
int par[MAXN][20];
int st[MAXN];
int en[MAXN];
int depth[MAXN];
void dfs_par(int cur, int prv) {
  if (prv) {
    for (vector<pair<int, char> >::iterator it = adj[cur].begin();; ++it) {
      if (it->first == prv) {
        adj[cur].erase(it);
        break;
      }
    }
  }
  par[cur][0] = prv;
  for (int i = 0; par[cur][i]; i++) {
    par[cur][i + 1] = par[par[cur][i]][i];
  }
  en[cur] = st[cur] + 1;
  for (size_t z = 0; z < adj[cur].size(); z++) {
    pair<int, char>& e = adj[cur][z];
    int nxt = e.first;
    pc[nxt] = e.second;
    depth[nxt] = depth[cur] + 1;
    st[nxt] = en[cur];
    dfs_par(nxt, cur);
    en[cur] = en[nxt];
  }
}
int lift(int a, int d) {
  for (int i = 0; (1 << i) <= d; i++) {
    if (d & (1 << i)) {
      a = par[a][i];
    }
  }
  return a;
}
int lca(int a, int b) {
  if (depth[a] < depth[b]) swap(a, b);
  a = lift(a, depth[a] - depth[b]);
  assert(depth[a] == depth[b]);
  if (a == b) return a;
  int i = 0;
  while (par[a][i]) i++;
  while (i--) {
    if (par[a][i] != par[b][i]) {
      a = par[a][i];
      b = par[b][i];
    }
  }
  assert(par[a][0] == par[b][0]);
  return par[a][0];
}
bool isanc(int a, int b) { return st[a] <= st[b] && en[b] <= en[a]; }
string getstr(int a, int b) {
  assert(isanc(b, a));
  string s;
  for (; a != b; a = par[a][0]) {
    s += pc[a];
  }
  return s;
}
const int MAXV = 2 * MAXL;
int V = 0;
int ch[MAXV][26];
int fail[MAXV];
vector<int> fail_ch[MAXV];
int fail_st[MAXV];
int fail_en[MAXV];
void reset_ah() {
  for (int v = 0; v < V; v++) {
    memset(ch[v], 0, sizeof(ch[v]));
    fail_ch[v].clear();
  }
  V = 1;
}
int insert_str(const string& s) {
  int n = int(s.size());
  int cur = 0;
  for (int i = 0; i < n; i++) {
    int v = int(s[i] - 'a');
    int& nxt = ch[cur][v];
    assert(V < MAXV);
    if (nxt == 0) nxt = V++;
    cur = nxt;
  }
  return cur;
}
void dfs_fail(int cur) {
  fail_en[cur] = fail_st[cur] + 1;
  for (size_t z = 0; z < fail_ch[cur].size(); z++) {
    int nxt = fail_ch[cur][z];
    fail_st[nxt] = fail_en[cur];
    dfs_fail(nxt);
    fail_en[cur] = fail_en[nxt];
  }
}
vector<pair<int, int> > evts[MAXN];
int ans[MAXM];
const int S = 1 << 20;
int seg[2 * S];
void dfs_ans(int cur, int state) {
  for (int a = fail_st[state] + S; a; a /= 2) {
    seg[a]++;
  }
  for (size_t z = 0; z < evts[cur].size(); z++) {
    pair<int, int>& evt = evts[cur][z];
    int s = 0;
    for (int a = fail_st[evt.first] + S, b = fail_en[evt.first] + S; a < b;
         a /= 2, b /= 2) {
      if (a & 1) {
        s += seg[a++];
      }
      if (b & 1) {
        s += seg[--b];
      }
    }
    if (evt.second >= 0) {
      ans[evt.second] += s;
    } else {
      ans[~evt.second] -= s;
    }
  }
  for (size_t z = 0; z < adj[cur].size(); z++) {
    pair<int, char>& e = adj[cur][z];
    int nxt = e.first;
    int v = int(e.second - 'a');
    dfs_ans(nxt, ch[state][v]);
  }
  for (int a = fail_st[state] + S; a; a /= 2) {
    seg[a]--;
  }
}
int main() {
  ios::sync_with_stdio(0), cin.tie(0);
  cin >> N;
  for (int i = 0; i < N - 1; i++) {
    int u, v;
    char c;
    cin >> u >> v >> c;
    adj[u].push_back(make_pair(v, c));
    adj[v].push_back(make_pair(u, c));
  }
  dfs_par(1, 0);
  cin >> M;
  for (int off = 0; off < M; off += B) {
    reset_ah();
    for (int i = 1; i <= N; i++) {
      evts[i].clear();
    }
    for (int q = off; q < M && q < off + B; q++) {
      int u, v;
      string s;
      cin >> u >> v >> s;
      int l = lca(u, v);
      assert(isanc(l, u));
      assert(isanc(l, v));
      {
        string sl =
            getstr(lift(u, max(0, depth[u] - depth[l] - int(s.size()) + 1)), l);
        string sr =
            getstr(lift(v, max(0, depth[v] - depth[l] - int(s.size()) + 1)), l);
        assert(max(sl.size(), sr.size()) < s.size());
        reverse(sr.begin(), sr.end());
        sl.append(sr);
        ans[q] += match(sl, s);
      }
      {
        int ends[2] = {v, u};
        for (int z = 0; z < 2; z++, reverse(s.begin(), s.end())) {
          int cur = ends[z];
          if (depth[cur] - depth[l] < int(s.size())) continue;
          int loc = insert_str(s);
          int tgt =
              lift(cur, max(depth[cur] - depth[l] - int(s.size()) + 1, 0));
          evts[tgt].push_back(make_pair(loc, ~q));
          evts[cur].push_back(make_pair(loc, q));
        }
      }
    }
    vector<int> ah_queue(1, 0);
    ah_queue.reserve(V);
    fail[0] = -1;
    for (size_t z = 0; z < ah_queue.size(); z++) {
      int cur = ah_queue[z];
      for (int v = 0; v < 26; v++) {
        int& nxt = ch[cur][v];
        int nfail = (fail[cur] == -1 ? 0 : ch[fail[cur]][v]);
        if (!nxt) {
          nxt = nfail;
        } else {
          ah_queue.push_back(nxt);
          fail[nxt] = nfail;
          fail_ch[nfail].push_back(nxt);
        }
      }
    }
    dfs_fail(0);
    assert(ah_queue.size() == size_t(V));
    dfs_ans(1, 0);
  }
  for (int i = 0; i < M; i++) {
    cout << ans[i] << '\n';
  }
  return 0;
}
