#include <bits/stdc++.h>

using namespace std;

const int K = 26;
const int N = 4e5+111;

int n, m;

int triePos[N];
vector<int> trieId[N];
vector<int> trieQuery[N];
int queryPos[N];
vector<int> G[N];

int res[N];

class ACAutomaton
{
public:
    class Node
    {
    public:
        int next[K];
        bool leaf = 0;
        int parent = -1;
        char pch;
        int link = -1;
        int go[K];

        Node(int parent = -1, char pch = '#'):parent(parent), pch(pch)
        {
            memset(next,-1,sizeof(next));
            memset(go,-1,sizeof(go));
        }

        int& operator[](int k)
        {
            return next[k];
        }
    };

    vector<Node> Tree;

    ACAutomaton()
    {
        Tree.emplace_back();
    }

    unsigned int size()
    {
        return Tree.size();
    }

    int add_string(const string &s)
    {
        int v = 0;
        for(char ch: s)
        {
            int c = ch - 'a';
            if(Tree[v][c] == -1)
            {
                Tree[v][c] = (int)Tree.size();
                Tree.emplace_back(v,ch);
            }
            v = Tree[v][c];
        }
        Tree[v].leaf = 1;
        return v;
    }

    int go(int v, char ch)
    {
        int c = ch - 'a';
        if(Tree[v].go[c] == -1)
        {
            if(Tree[v][c] != -1) Tree[v].go[c] = Tree[v][c];
            else Tree[v].go[c] = (v == 0 ? 0 : go(get_link(v), ch));
        }
        return Tree[v].go[c];
    }

    int get_link(int v)
    {
        if(Tree[v].link == -1)
        {
            if(v == 0 || Tree[v].parent == 0) Tree[v].link = 0;
            else Tree[v].link = go(get_link(Tree[v].parent), Tree[v].pch);
        }
        return Tree[v].link;
    }
};

class Trie
{
public:
    class Node
    {
    public:
        int next[K];

        Node()
        {
            memset(next,-1,sizeof(next));
        }

        int& operator[](int k)
        {
            return next[k];
        }
    };

    vector<Node> Tree;

    Trie()
    {
        Tree.emplace_back();
    }

    int add_letter(int v, char ch)
    {
        int c = ch - 'a';
        if(Tree[v][c] == -1)
        {
            Tree[v][c] = (int)Tree.size();
            Tree.emplace_back();
        }
        return Tree[v][c];
    }
};

class FenwichTree
{
private:
    int bit[N];
    int tm, tin[N], tout[N];
public:
    FenwichTree()
    {
        tm = 1;
        memset(bit,0,sizeof(bit));
        memset(tin,0,sizeof(tin));
        memset(tout,0,sizeof(tout));
    }

    void visit(int u)
    {
        tin[u] = tm++;
        for(auto v: G[u]) visit(v);
        tout[u] = tm;
    }

    void update(int u, int val)
    {
        for(int i = tin[u]; i < N; i += i&-i) bit[i] += val;
    }

    int get(int x)
    {
        int sum = 0;
        for(int i = x; i > 0; i -= i&-i) sum += bit[i];
        return sum;
    }

    int sum(int u)
    {
        return get(tout[u]-1) - get(tin[u]-1);
    }

};

ACAutomaton ac = ACAutomaton();
Trie trie = Trie();
FenwichTree ft = FenwichTree();

void update(int trieNode, int acNode)
{
    ft.update(acNode, 1);
    for(auto id: trieId[trieNode])
    {
        for(auto q: trieQuery[id])
        {
            res[q] = ft.sum(queryPos[q]);
        }
    }
    for(char ch = 'a'; ch <= 'z'; ++ch)
    {
        int c = ch - 'a';
        if(trie.Tree[trieNode][c] != -1)
        {
            update(trie.Tree[trieNode][c], ac.go(acNode,ch));
        }
    }
    ft.update(acNode,-1);
}

int main()
{
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin>>n;
    for(int i = 1; i <= n; ++i)
    {
        int type, u = 0;
        char ch;
        cin>>type;
        if(type == 1) cin>>ch;
        else cin>>u>>ch;
        triePos[i] = trie.add_letter(triePos[u],ch);
        trieId[triePos[i]].push_back(i);
    }
    cin>>m;
    for(int i = 1; i <= m; ++i)
    {
        int u;
        string s;
        cin>>u>>s;
        trieQuery[u].push_back(i);
        queryPos[i] = ac.add_string(s);
    }

    for(int i = 1; i < (int)ac.size(); ++i) G[ac.get_link(i)].push_back(i);

    ft.visit(0);
    update(0,0);

    for(int i = 1; i <= m; ++i) cout << res[i] << '\n';

    return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int K = 26;
const int N = 4e5+111;

int n, m;

int triePos[N];
vector<int> trieId[N];
vector<int> trieQuery[N];
int queryPos[N];
vector<int> G[N];

int res[N];

class ACAutomaton
{
public:
    class Node
    {
    public:
        int next[K];
        bool leaf = 0;
        int parent = -1;
        char pch;
        int link = -1;
        int go[K];

        Node(int parent = -1, char pch = '#'):parent(parent), pch(pch)
        {
            memset(next,-1,sizeof(next));
            memset(go,-1,sizeof(go));
        }

        int& operator[](int k)
        {
            return next[k];
        }
    };

    vector<Node> Tree;

    ACAutomaton()
    {
        Tree.emplace_back();
    }

    unsigned int size()
    {
        return Tree.size();
    }

    int add_string(const string &s)
    {
        int v = 0;
        for(char ch: s)
        {
            int c = ch - 'a';
            if(Tree[v][c] == -1)
            {
                Tree[v][c] = (int)Tree.size();
                Tree.emplace_back(v,ch);
            }
            v = Tree[v][c];
        }
        Tree[v].leaf = 1;
        return v;
    }

    int go(int v, char ch)
    {
        int c = ch - 'a';
        if(Tree[v].go[c] == -1)
        {
            if(Tree[v][c] != -1) Tree[v].go[c] = Tree[v][c];
            else Tree[v].go[c] = (v == 0 ? 0 : go(get_link(v), ch));
        }
        return Tree[v].go[c];
    }

    int get_link(int v)
    {
        if(Tree[v].link == -1)
        {
            if(v == 0 || Tree[v].parent == 0) Tree[v].link = 0;
            else Tree[v].link = go(get_link(Tree[v].parent), Tree[v].pch);
        }
        return Tree[v].link;
    }
};

class Trie
{
public:
    class Node
    {
    public:
        int next[K];

        Node()
        {
            memset(next,-1,sizeof(next));
        }

        int& operator[](int k)
        {
            return next[k];
        }
    };

    vector<Node> Tree;

    Trie()
    {
        Tree.emplace_back();
    }

    int add_letter(int v, char ch)
    {
        int c = ch - 'a';
        if(Tree[v][c] == -1)
        {
            Tree[v][c] = (int)Tree.size();
            Tree.emplace_back();
        }
        return Tree[v][c];
    }
};

class FenwichTree
{
private:
    int bit[N];
    int tm, tin[N], tout[N];
public:
    FenwichTree()
    {
        tm = 0;
        memset(bit,0,sizeof(bit));
        memset(tin,0,sizeof(tin));
        memset(tout,0,sizeof(tout));
    }

    void visit(int u)
    {
        tin[u] = ++tm;
        for(auto v: G[u]) visit(v);
        tout[u] = tm;
    }

    void update(int u, int val)
    {
        for(int i = tin[u]; i < N; i += i&-i) bit[i] += val;
    }

    int get(int x)
    {
        int sum = 0;
        for(int i = x; i > 0; i -= i&-i) sum += bit[i];
        return sum;
    }

    int sum(int u)
    {
        return get(tout[u]) - get(tin[u]-1);
    }

};

ACAutomaton ac = ACAutomaton();
Trie trie = Trie();
FenwichTree ft = FenwichTree();

void update(int trieNode, int acNode)
{
    ft.update(acNode, 1);
    for(auto id: trieId[trieNode])
    {
        for(auto q: trieQuery[id])
        {
            res[q] = ft.sum(queryPos[q]);
        }
    }
    for(char ch = 'a'; ch <= 'z'; ++ch)
    {
        int c = ch - 'a';
        if(trie.Tree[trieNode][c] != -1)
        {
            update(trie.Tree[trieNode][c], ac.go(acNode,ch));
        }
    }
    ft.update(acNode,-1);
}

int main()
{
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    cin>>n;
    for(int i = 1; i <= n; ++i)
    {
        int type, u = 0;
        char ch;
        cin>>type;
        if(type == 1) cin>>ch;
        else cin>>u>>ch;
        triePos[i] = trie.add_letter(triePos[u],ch);
        trieId[triePos[i]].push_back(i);
    }
    cin>>m;
    for(int i = 1; i <= m; ++i)
    {
        int u;
        string s;
        cin>>u>>s;
        trieQuery[u].push_back(i);
        queryPos[i] = ac.add_string(s);
    }

    for(int i = 1; i < (int)ac.size(); ++i) G[ac.get_link(i)].push_back(i);

    ft.visit(0);
    update(0,0);

    for(int i = 1; i <= m; ++i) cout << res[i] << '\n';

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define f first
#define s second
#define pb push_back
#define reset(a,b) memset(a,b,sizeof a);
#define ALL(x) x.begin(),x.end()

template <typename T>
void cetak(T t){cout << t << ')' << endl;}
template <typename T, typename... V>
void cetak(T t, V... v) {cout << t; if (sizeof...(v)) cerr << ", "; cetak(v...);}

#define debug(x...) cout<< '(' << #x << ") = ("; cetak(x)
#define sz(x) (int)(x.size())
#define lt(x) (int)(x.length())

const int MOD = 1e9 + 7;
const int mx = 5e5 + 10;

const int N = 5e5 + 5;

vector<int> g[mx];

struct AhoCorasick {
	int trie[N][26];
	int fail[N];
	int saiz;

	AhoCorasick() {
		memset(trie[0],-1,sizeof trie[0]);
		saiz = 0;
	}

	int add(string str) {
		int cur = 0;
		for(int i = 0 ; i < str.length() ; i++) {
			//checkChar(str[i]);
			int nex = str[i] - 'a';
			if(trie[cur][nex] == -1) {
				trie[cur][nex] = ++saiz;
				memset(trie[saiz],-1,sizeof trie[saiz]);
			}
			cur = trie[cur][nex];
		}
        return cur;
	}

	void build() {
		queue<int> q;
		fail[0] = 0;

		for(int i = 0 ; i < 26 ; i++)
			if(trie[0][i] == -1)
				trie[0][i] = 0;
			else {
				int nex = trie[0][i];
				fail[nex] = 0;
				q.push(nex);
			}

		while(!q.empty()) {
			int now = q.front();
			q.pop();
            if(now != fail[now]) g[fail[now]].pb(now);

			for(int i = 0 ; i < 26 ; i++)
				if(trie[now][i] == -1)
					trie[now][i] = trie[fail[now]][i];
				else {
					int nex = trie[now][i];
					fail[nex] = trie[fail[now]][i];
					q.push(nex);
				}
		}
	}

	int getIndex(string str) {
		int cur = 0;
		for(int i = 0 ; i < str.length() ; i++) {
			//checkChar(str[i]);
			cur = trie[cur][str[i] - 'a'];
		}
		return cur;
	}

} ini;

int n, p[mx], q, di[mx], idx, in[mx], out[mx];
char c[mx];
vector<int> query[mx];
string ss[mx];

void dfs(int now){
    in[now] = ++idx;
    for(int i : g[now]) dfs(i);
    out[now] = idx;
}

vector<int> G[mx];
int jaw[mx];

int bit[mx];

void upd(int idx, int val){
    for(; idx <= 5e5; idx += idx & -idx) bit[idx] += val;
}

int cari(int i){
    int ret = 0;
    for(; i; i -= i & -i) ret += bit[i];
    return ret;
}

void DFS(int now, int cur){
    for(int i : query[now]){
        jaw[i] = cari(out[di[i]]) - cari(in[di[i]] - 1);
    }
    for(int i : G[now]){
        int nex = ini.trie[cur][c[i] - 'a'];
        upd(in[nex], 1);
        DFS(i, nex);
        upd(in[nex], -1);
    }
}

int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cin >> n;
    for(int i = 1; i <= n; i++){
        int t;
        cin >> t;
        if(t == 1) cin >> c[i];
        else cin >> p[i] >> c[i];
    }
    for(int i = 1; i <= n; i++){
        G[p[i]].pb(i);
    }
    cin >> q;
    for(int i = 1; i <= q; i++){
        int x;
        cin >> x >> ss[i];
        query[x].pb(i);
        di[i] = ini.add(ss[i]);
    }
    ini.build();
    int N = ini.saiz;
    dfs(0);
    DFS(0, 0);
    for(int i = 1; i <= q; i++) cout << jaw[i] << '\n';
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define trav(a, x) for(auto& a : x)
#define all(x) x.begin(), x.end()
#define sz(x) (int)(x).size()
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;

struct AhoCorasick {
  enum {alpha = 26, first = 'a'};
  struct Node {
    // (nmatches is optional )
    int back, next[alpha], start = -1, end = -1, nmatches = 0;
    Node(int v) { memset(next, v, sizeof(next)); }
  };
  vector<Node> N;
  vector<int> backp;
  void insert(string& s, int j) {
    assert(!s.empty());
    int n = 0;
    trav(c, s) {
      int& m = N[n].next[c - first];
      if (m == -1) { n = m = sz(N); N.emplace_back(-1); }
      else n = m;
    }
    if (N[n].end == -1) N[n].start = j;
    backp.push_back(N[n].end);
    N[n].end = j;
    N[n].nmatches++;
  }
  AhoCorasick(vector<string>& pat) {
    N.emplace_back(-1);
    rep(i,0,sz(pat)) insert(pat[i], i);
    N[0].back = sz(N);
    N.emplace_back(0);
    queue<int> q;
    for (q.push(0); !q.empty(); q.pop()) {
      int n = q.front(), prev = N[n].back;
      rep(i,0,alpha) {
	int &ed = N[n].next[i], y = N[prev].next[i];
	if (ed == -1) ed = y;
	else {
	  N[ed].back = y;
	  (N[ed].end == -1 ? N[ed].end : backp[N[ed].start])
	    = N[y].end;
	  N[ed].nmatches += N[y].nmatches;
	  q.push(ed);
	}
      }
    }
  }
  vi find(string word) {
    int n = 0;
    vi res; // l l count = 0;
    trav(c, word) {
      n = N[n].next[c - first];
      res.push_back(N[n].end);
      // count += N[n ] . nmatches ;
    }
    return res;
  }
  vector<vi> findAll(vector<string>& pat, string word) {
    vi r = find(word);
    vector<vi> res(sz(word));
    rep(i,0,sz(word)) {
      int ind = r[i];
      while (ind != -1) {
	res[i - sz(pat[ind]) + 1].push_back(ind);
	ind = backp[ind];
      }
    }
    return res;
  }

  int getPos(string word) {
    int n = 0;
    trav(c, word) {
      n = N[n].next[c - first];
    }
    return N[n].end;
  }
};

vector<string> upatterns;

const int nax = 4e5+10;
map<char,int> trie[nax];
int ind[nax];
int len = 1;
vector<pair<int,int>> query[nax];
int ans[nax];
int matches[nax];

void dfs(int p, AhoCorasick&aho, int ahi = 0) {//, string path = "") {
  //cout << "Node: " << path << endl;
  if (1) {
    int ind = aho.N[ahi].end;
    //cout << ahi << ' ';
    while (ind != -1) {
      //cout << upatterns[ind] << ' ';
      matches[ind]++;
      ind = aho.backp[ind];
    }
    //cout << endl;
  }
  for (auto q : query[p]) {
    ans[q.first] = matches[q.second];
  }
  for (auto c : trie[p]) {
    int nahi = aho.N[ahi].next[c.first-aho.first];
    dfs(c.second, aho, nahi);//, path+c.first);
  }
  if (1) {
    int ind = aho.N[ahi].end;
    while (ind != -1) {
      matches[ind]--;
      ind = aho.backp[ind];
    }
  }
}

void print(int p, string path = "") {
  cout << path << endl;
  for (auto c : trie[p]) {
    print(c.second, path+c.first);
  }
}

int main() {
  ios::sync_with_stdio(0); cin.tie(0);
  int n;
  cin >> n;
  for (int i = 0; i < n; i++) {
    int t;
    cin >> t;
    int p = 0;
    char c;
    if (t == 1) {
      cin >> c;
    } else if (t == 2) {
      cin >> p >> c;
      p = ind[p-1];
    }
    if (!trie[p].count(c)) {
      trie[p][c] = len++;
    }
    ind[i] = trie[p][c];
  }

  int q;
  cin >> q;
  map<string,vector<pair<int,int>>> patterns;
  for (int i = 0; i < q; i++) {
    int p;
    string t;
    cin >> p >> t;
    patterns[t].push_back({ind[p-1],i});
  }
  for (auto p : patterns)
    upatterns.push_back(p.first);
  /*for (string s : upatterns)
    cout << "|" << s << "| ";
    cout << endl;*/
  AhoCorasick aho(upatterns);
  /*for (int i : aho.find("dada"))
    cout << i << endl;
    return 0;*/
  for (auto p : patterns) {
    int i = aho.getPos(p.first);
    //cout << upatterns[i] << ' ' << p.first << endl;
    for (auto q : p.second)
      query[q.first].push_back({q.second, i});
  }

  dfs(0, aho);
  for (int i = 0; i < q; i++)
    cout << ans[i] << '\n';
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define trav(a, x) for(auto& a : x)
#define all(x) x.begin(), x.end()
#define sz(x) (int)(x).size()
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;

struct AhoCorasick {
  enum {alpha = 26, first = 'a'};
  struct Node {
    // (nmatches is optional )
    int back, next[alpha], start = -1, end = -1, nmatches = 0;
    Node(int v) { memset(next, v, sizeof(next)); }
  };
  vector<Node> N;
  vector<int> backp;
  void insert(string& s, int j) {
    assert(!s.empty());
    int n = 0;
    trav(c, s) {
      int& m = N[n].next[c - first];
      if (m == -1) { n = m = sz(N); N.emplace_back(-1); }
      else n = m;
    }
    if (N[n].end == -1) N[n].start = j;
    backp.push_back(N[n].end);
    N[n].end = j;
    N[n].nmatches++;
  }
  AhoCorasick(vector<string>& pat) {
    N.emplace_back(-1);
    rep(i,0,sz(pat)) insert(pat[i], i);
    N[0].back = sz(N);
    N.emplace_back(0);
    queue<int> q;
    for (q.push(0); !q.empty(); q.pop()) {
      int n = q.front(), prev = N[n].back;
      rep(i,0,alpha) {
	int &ed = N[n].next[i], y = N[prev].next[i];
	if (ed == -1) ed = y;
	else {
	  N[ed].back = y;
	  (N[ed].end == -1 ? N[ed].end : backp[N[ed].start])
	    = N[y].end;
	  N[ed].nmatches += N[y].nmatches;
	  q.push(ed);
	}
      }
    }
  }
  vi find(string word) {
    int n = 0;
    vi res; // l l count = 0;
    trav(c, word) {
      n = N[n].next[c - first];
      res.push_back(N[n].end);
      // count += N[n ] . nmatches ;
    }
    return res;
  }
  vector<vi> findAll(vector<string>& pat, string word) {
    vi r = find(word);
    vector<vi> res(sz(word));
    rep(i,0,sz(word)) {
      int ind = r[i];
      while (ind != -1) {
	res[i - sz(pat[ind]) + 1].push_back(ind);
	ind = backp[ind];
      }
    }
    return res;
  }

  int getPos(string word) {
    int n = 0;
    trav(c, word) {
      n = N[n].next[c - first];
    }
    return N[n].end;
  }
};

vector<string> upatterns;

const int nax = 4e5+10;
map<char,int> trie[nax];
int ind[nax];
int len = 1;
vector<pair<int,int>> query[nax];
int ans[nax];
int matches[nax];

void dfs(int p, AhoCorasick&aho, int ahi = 0, string path = "") {
  //cout << "Node: " << path << endl;
  if (1) {
    int ind = aho.N[ahi].end;
    //cout << ahi << ' ';
    while (ind != -1) {
      //cout << upatterns[ind] << ' ';
      matches[ind]++;
      ind = aho.backp[ind];
    }
    //cout << endl;
  }
  for (auto q : query[p]) {
    ans[q.first] = matches[q.second];
  }
  for (auto c : trie[p]) {
    int nahi = aho.N[ahi].next[c.first-aho.first];
    dfs(c.second, aho, nahi, path+c.first);
  }
  if (1) {
    int ind = aho.N[ahi].end;
    while (ind != -1) {
      matches[ind]--;
      ind = aho.backp[ind];
    }
  }
}

void print(int p, string path = "") {
  cout << path << endl;
  for (auto c : trie[p]) {
    print(c.second, path+c.first);
  }
}

int main() {
  ios::sync_with_stdio(0); cin.tie(0);
  int n;
  cin >> n;
  for (int i = 0; i < n; i++) {
    int t;
    cin >> t;
    int p = 0;
    char c;
    if (t == 1) {
      cin >> c;
    } else if (t == 2) {
      cin >> p >> c;
      p = ind[p-1];
    }
    if (!trie[p].count(c)) {
      trie[p][c] = len++;
    }
    ind[i] = trie[p][c];
  }

  int q;
  cin >> q;
  map<string,vector<pair<int,int>>> patterns;
  for (int i = 0; i < q; i++) {
    int p;
    string t;
    cin >> p >> t;
    patterns[t].push_back({ind[p-1],i});
  }
  for (auto p : patterns)
    upatterns.push_back(p.first);
  /*for (string s : upatterns)
    cout << "|" << s << "| ";
    cout << endl;*/
  AhoCorasick aho(upatterns);
  /*for (int i : aho.find("dada"))
    cout << i << endl;
    return 0;*/
  for (auto p : patterns) {
    int i = aho.getPos(p.first);
    //cout << upatterns[i] << ' ' << p.first << endl;
    for (auto q : p.second)
      query[q.first].push_back({q.second, i});
  }

  dfs(0, aho);
  for (int i = 0; i < q; i++)
    cout << ans[i] << '\n';
}


#include<bits/stdc++.h>
#define lowbit(x) x&-x
using namespace std;

const int maxn=8e5+999;

int tot,n,m;

namespace BIT{
	int c[maxn];
	void add(int pos,int x){
		while(pos<=n+m){
			c[pos]+=x;pos+=lowbit(pos);
		}
	}
	int query(int pos){
		int ans=0;
		while(pos){
			ans+=c[pos];pos-=lowbit(pos);
		}
		return ans;
	}
}

namespace graph{
	struct edge{
		int to,nxt;
	}e[maxn];
	int head[maxn],tott;
	void add_edge(int x,int y){
		e[++tott].to=y;
		e[tott].nxt=head[x];
		head[x]=tott;
	}
}

namespace AC_automaton{
	int fa[maxn],ch[maxn][27],trie[maxn][27];
	int insert(char *s)
	{
		int now=0,len=strlen(s);
		for(int i=0;i<len;i++)
		{
			int c=s[i]-'a';
			if(!ch[now][c])ch[now][c]=++tot;
			now=ch[now][c];
		}
		return now;
	}
	void build()
	{
		queue<int>q;
		for(int i=0;i<26;i++)if(ch[0][i])q.push(ch[0][i]);
		while(q.size())
		{
			int r=q.front();q.pop();
			for(int c=0;c<26;c++)
			{
				if(!ch[r][c]){
					ch[r][c]=ch[fa[r]][c];
					continue;
				}
				q.push(ch[r][c]);
				int j=fa[r];
				while(j&&!ch[j][c])j=fa[j];
				fa[ch[r][c]]=ch[j][c];
			}
		}
	}
}

using namespace BIT;
using namespace AC_automaton;
using namespace graph;

vector<pair<int,int> >v[maxn];
int End[maxn],dfn[maxn],clk,ans[maxn],siz[maxn];
char s[maxn];

void dfs(int x)
{
	dfn[x]=++clk;siz[x]=1;
	for(int i=head[x];i;i=e[i].nxt)
		dfs(e[i].to),siz[x]+=siz[e[i].to];
}

void dfs2(int x)
{
	if(x)add(dfn[x],1);
	for(int j=0;j<v[x].size();j++)
		ans[v[x][j].second]=query(dfn[v[x][j].first]-1+siz[v[x][j].first])-query(dfn[v[x][j].first]-1);
	for(int i=0;i<26;i++)
	{
		int y=trie[x][i];
		if(y)dfs2(y);
	}
	add(dfn[x],-1);
}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		int opt;
		scanf("%d",&opt);
		if(opt==1){
			scanf("%s",s);
			if(!ch[0][s[0]-'a'])ch[0][s[0]-'a']=++tot;
			End[i]=ch[0][s[0]-'a'];
		}
		else
		{
			int num;
			scanf("%d",&num);
			scanf("%s",s);
			if(!ch[End[num]][s[0]-'a'])ch[End[num]][s[0]-'a']=++tot;
			End[i]=ch[End[num]][s[0]-'a'];
		}
	}
	scanf("%d",&m);
	int num;
	for(int i=1;i<=m;i++)
	{
		scanf("%d",&num);
		scanf("%s",s);
		int x=insert(s);
		v[End[num]].push_back(make_pair(x,i));//¼ÓÈëÒª²éÑ¯µÄ½Úµã
	}
	memcpy(trie,ch,sizeof(ch));//¼ÇÂ¼trieÊ÷
	build();
	for(int i=1;i<=tot;i++)add_edge(fa[i],i);
	dfs(0);
	dfs2(0);
	for(int i=1;i<=m;i++)cout<<ans[i]<<endl;
}


#include<bits/stdc++.h>
#define lowbit(x) x&-x
using namespace std;

const int maxn=8e5+999;

int tot,n,m;

namespace BIT{
	int c[maxn];
	void add(int pos,int x){
		while(pos<maxn){
			c[pos]+=x;pos+=lowbit(pos);
		}
	}
	int query(int pos){
		int ans=0;
		while(pos){
			ans+=c[pos];pos-=lowbit(pos);
		}
		return ans;
	}
}

namespace graph{
	struct edge{
		int to,nxt;
	}e[maxn];
	int head[maxn],tott;
	void add_edge(int x,int y){
		e[++tott].to=y;
		e[tott].nxt=head[x];
		head[x]=tott;
	}
}

namespace AC_automaton{
	int fa[maxn],ch[maxn][27],trie[maxn][27];
	int insert(char *s)
	{
		int now=0,len=strlen(s);
		for(int i=0;i<len;i++)
		{
			int c=s[i]-'a';
			if(!ch[now][c])ch[now][c]=++tot;
			now=ch[now][c];
		}
		return now;
	}
	void build()
	{
		queue<int>q;
		for(int i=0;i<26;i++)if(ch[0][i])q.push(ch[0][i]);
		while(q.size())
		{
			int r=q.front();q.pop();
			for(int c=0;c<26;c++)
			{
				if(!ch[r][c]){
					ch[r][c]=ch[fa[r]][c];
					continue;
				}
				q.push(ch[r][c]);
				int j=fa[r];
				while(j&&!ch[j][c])j=fa[j];
				fa[ch[r][c]]=ch[j][c];
			}
		}
	}
}

using namespace BIT;
using namespace AC_automaton;
using namespace graph;

vector<pair<int,int> >v[maxn];
int End[maxn],dfn[maxn],clk,ans[maxn],siz[maxn];
char s[maxn];

void dfs(int x)
{
	dfn[x]=++clk;siz[x]=1;
	for(int i=head[x];i;i=e[i].nxt)
		dfs(e[i].to),siz[x]+=siz[e[i].to];
}

void dfs2(int x)
{
	if(x)add(dfn[x],1);
	for(int j=0;j<v[x].size();j++)
		ans[v[x][j].second]=query(dfn[v[x][j].first]-1+siz[v[x][j].first])-query(dfn[v[x][j].first]-1);
	for(int i=0;i<26;i++)
	{
		int y=trie[x][i];
		if(y)dfs2(y);
	}
	add(dfn[x],-1);
}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		int opt;
		scanf("%d",&opt);
		if(opt==1){
			scanf("%s",s);
			if(!ch[0][s[0]-'a'])ch[0][s[0]-'a']=++tot;
			End[i]=ch[0][s[0]-'a'];
		}
		else
		{
			int num;
			scanf("%d",&num);
			scanf("%s",s);
			if(!ch[End[num]][s[0]-'a'])ch[End[num]][s[0]-'a']=++tot;
			End[i]=ch[End[num]][s[0]-'a'];
		}
	}
	scanf("%d",&m);
	int num;
	for(int i=1;i<=m;i++)
	{
		scanf("%d",&num);
		scanf("%s",s);
		int x=insert(s);
		v[End[num]].push_back(make_pair(x,i));//¼ÓÈëÒª²éÑ¯µÄ½Úµã
	}
	memcpy(trie,ch,sizeof(ch));//¼ÇÂ¼trieÊ÷
	build();
	for(int i=1;i<=tot;i++)add_edge(fa[i],i);
	dfs(0);
	dfs2(0);
	for(int i=1;i<=m;i++)cout<<ans[i]<<endl;
}


#include<bits/stdc++.h>
#define lowbit(x) x&-x
using namespace std;

const int maxn=8e5+999;

int n,m;

namespace BIT{
	int c[maxn];
	void add(int pos,int x){
		while(pos<=n){
			c[pos]+=x;pos+=lowbit(pos);
		}
	}
	int query(int pos){
		int ans=0;
		while(pos){
			ans+=c[pos];pos-=lowbit(pos);
		}
		return ans;
	}
}

namespace graph{
	struct edge{
		int to,nxt;
	}e[maxn];
	int head[maxn],tott;
	void add_edge(int x,int y){
		e[++tott].to=y;
		e[tott].nxt=head[x];
		head[x]=tott;
	}
}

namespace AC_automaton{
	int tot,fa[maxn],ch[maxn][27],trie[maxn][27];
	int insert(char *s)
	{
		int now=0,len=strlen(s);
		for(int i=0;i<len;i++)
		{
			int c=s[i]-'a';
			if(!ch[now][c])ch[now][c]=++tot;
			now=ch[now][c];
		}
		return now;
	}
	void build()
	{
		queue<int>q;
		for(int i=0;i<26;i++)if(ch[0][i])q.push(ch[0][i]);
		while(q.size())
		{
			int r=q.front();q.pop();
			for(int c=0;c<26;c++)
			{
				if(!ch[r][c]){
					ch[r][c]=ch[fa[r]][c];
					continue;
				}
				q.push(ch[r][c]);
				int j=fa[r];
				while(j&&!ch[j][c])j=fa[j];
				fa[ch[r][c]]=ch[j][c];
			}
		}
	}
}

using namespace BIT;
using namespace AC_automaton;
using namespace graph;

vector<pair<int,int> >v[maxn];
int End[maxn],dfn[maxn],clk,ans[maxn],siz[maxn];
char s[maxn];

void dfs(int x)
{
	dfn[x]=++clk;siz[x]=1;
	for(int i=head[x];i;i=e[i].nxt)
		dfs(e[i].to),siz[x]+=siz[e[i].to];
}

void dfs2(int x)
{
	add(dfn[x],1);
	for(int j=0;j<v[x].size();j++)
		ans[v[x][j].second]=query(dfn[v[x][j].first]-1+siz[v[x][j].first])-query(dfn[v[x][j].first]-1);
	for(int i=0;i<26;i++)
	{
		int y=trie[x][i];
		if(y)dfs2(y);
	}
	add(dfn[x],-1);
}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		int opt;
		scanf("%d",&opt);
		if(opt==1){
			scanf("%s",s);
			if(!ch[0][s[0]-'a'])ch[0][s[0]-'a']=++tot;
			End[i]=ch[0][s[0]-'a'];
		}
		else
		{
			int num;
			scanf("%d",&num);
			scanf("%s",s);
			if(!ch[End[num]][s[0]-'a'])ch[End[num]][s[0]-'a']=++tot;
			End[i]=ch[End[num]][s[0]-'a'];
		}
	}
	scanf("%d",&m);
	int num;
	for(int i=1;i<=m;i++)
	{
		scanf("%d",&num);
		scanf("%s",s);
		int x=insert(s);
		v[End[num]].push_back(make_pair(x,i));//¼ÓÈëÒª²éÑ¯µÄ½Úµã
	}
	memcpy(trie,ch,sizeof(ch));//¼ÇÂ¼trieÊ÷
	build();
	for(int i=1;i<=tot;i++)add_edge(fa[i],i);
	dfs(0);
	dfs2(0);
	for(int i=1;i<=m;i++)cout<<ans[i]<<endl;
}


#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#include <cmath>
#include <bitset>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <algorithm>
#include <complex>
#include <unordered_map>
#include <unordered_set>
#include <random>
#include <cassert>
#include <fstream>
#include <utility>
#include <functional>
#define popcount __builtin_popcount
using namespace std;
typedef long long int ll;
typedef pair<int, int> P;
template< int char_size >
struct TrieNode {
  int nxt[char_size];

  int exist;
  vector< int > accept;

  TrieNode() : exist(0) {
    memset(nxt, -1, sizeof(nxt));
  }
};

template< int char_size, int margin >
struct Trie {
  using Node = TrieNode< char_size >;

  vector< Node > nodes;
  int root;

  Trie() : root(0) {
    nodes.push_back(Node());
  }

  void update_direct(int node, int id) {
    nodes[node].accept.push_back(id);
  }

  void update_child(int node, int child, int id) {
    ++nodes[node].exist;
  }

  void add(const string &str, int str_index, int node_index, int id) {
    if(str_index == str.size()) {
      update_direct(node_index, id);
    } else {
      const int c = str[str_index] - margin;
      if(nodes[node_index].nxt[c] == -1) {
        nodes[node_index].nxt[c] = (int) nodes.size();
        nodes.push_back(Node());
      }
      add(str, str_index + 1, nodes[node_index].nxt[c], id);
      update_child(node_index, nodes[node_index].nxt[c], id);
    }
  }

  void add(const string &str, int id) {
    add(str, 0, 0, id);
  }

  void add(const string &str) {
    add(str, nodes[0].exist);
  }

  void query(const string &str, const function< void(int) > &f, int str_index, int node_index) {
    for(auto &idx : nodes[node_index].accept) f(idx);
    if(str_index == str.size()) {
      return;
    } else {
      const int c = str[str_index] - margin;
      if(nodes[node_index].nxt[c] == -1) return;
      query(str, f, str_index + 1, nodes[node_index].nxt[c]);
    }
  }

  void query(const string &str, const function< void(int) > &f) {
    query(str, f, 0, 0);
  }

  int count() const {
    return (nodes[0].exist);
  }

  int size() const {
    return ((int) nodes.size());
  }
};
template< int char_size, int margin >
struct AhoCorasick : Trie< char_size + 1, margin > {
  using Trie< char_size + 1, margin >::Trie;

  const int FAIL = char_size;
  vector< int > correct;

  void build(bool heavy = true) {
    correct.resize(this->size());
    for(int i = 0; i < this->size(); i++) {
      correct[i] = (int) this->nodes[i].accept.size();
    }
    queue< int > que;
    for(int i = 0; i <= char_size; i++) {
      if(~this->nodes[0].nxt[i]) {
        this->nodes[this->nodes[0].nxt[i]].nxt[FAIL] = 0;
        que.emplace(this->nodes[0].nxt[i]);
      } else {
        this->nodes[0].nxt[i] = 0;
      }
    }
    while(!que.empty()) {
      auto &now = this->nodes[que.front()];
      correct[que.front()] += correct[now.nxt[FAIL]];
      que.pop();
      for(int i = 0; i < char_size; i++) {
        if(now.nxt[i] == -1) continue;
        int fail = now.nxt[FAIL];
        while(this->nodes[fail].nxt[i] == -1) fail = this->nodes[fail].nxt[FAIL];
        this->nodes[now.nxt[i]].nxt[FAIL] = this->nodes[fail].nxt[i];
        if(heavy) {
          auto &u = this->nodes[now.nxt[i]].accept;
          auto &v = this->nodes[this->nodes[fail].nxt[i]].accept;
          vector< int > accept;
          set_union(begin(u), end(u), begin(v), end(v), back_inserter(accept));
          u = accept;
        }
        que.emplace(now.nxt[i]);
      }

    }
  }

  map< int, int > match(const string &str, int now = 0) {
    map< int, int > result;
    for(auto &c : str) {
      while(this->nodes[now].nxt[c - margin] == -1) now = this->nodes[now].nxt[FAIL];
      now = this->nodes[now].nxt[c - margin];
      for(auto &v : this->nodes[now].accept) result[v] += 1;
    }
    return result;
  }

  pair< int, int > move(const char &c, int now) {
    int sum = 0;
    while(this->nodes[now].nxt[c - margin] == -1) now = this->nodes[now].nxt[FAIL];
    now = this->nodes[now].nxt[c - margin];
    sum += correct[now];
    return {sum, now};
  }
};
vector<int> g[400010];
char c[400010];
int n, m;
int k[400010];
AhoCorasick<26, 'a'> aho;
int cnt[400010];
map<int, vector<int>> mp;
void dfs(int x, int now){
	for(auto y:g[x]){
		P pr=aho.move(c[y], now);
		mp[pr.second].push_back(y);
		dfs(y, pr.second);
	}
}
vector<int> v1[400010]; vector<P> v2[400010];
int cnt1[400010];
void dfs1(int x){
	for(auto i:v1[x]){
		cnt1[i]++;
	}
	for(auto pr:v2[x]){
		cnt[pr.second]+=cnt1[pr.first];
	}
	for(auto y:g[x]) dfs1(y);
	for(auto i:v1[x]){
		cnt1[i]--;
	}
}
int main()
{
	cin>>n;
	for(int i=1; i<=n; i++){
		int t;
		cin>>t;
		if(t==1){
			cin>>c[i];
			g[0].push_back(i);
		}else{
			int j; cin>>j>>c[i];
			g[j].push_back(i);
		}
	}
	cin>>m;
	for(int i=0; i<m; i++){
		cin>>k[i];
		string t; cin>>t;
		aho.add(t, i);
	}
	aho.build();
	dfs(0, 0);
	int l=0;
	for(auto pr:mp){
		vector<int> v=pr.second, w=aho.nodes[pr.first].accept;
		for(auto x:v) v1[x].push_back(l);
		for(auto i:w) v2[k[i]].push_back({l, i});
		l++;
	}
	dfs1(0);
	for(int i=0; i<m; i++){
		printf("%d\n", cnt[i]);
	}
	return 0;
}


#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#include <cmath>
#include <bitset>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <algorithm>
#include <complex>
#include <unordered_map>
#include <unordered_set>
#include <random>
#include <cassert>
#include <fstream>
#include <utility>
#include <functional>
#define popcount __builtin_popcount
using namespace std;
typedef long long int ll;
typedef pair<int, int> P;
template< int char_size >
struct TrieNode {
  int nxt[char_size];

  int exist;
  vector< int > accept;

  TrieNode() : exist(0) {
    memset(nxt, -1, sizeof(nxt));
  }
};

template< int char_size, int margin >
struct Trie {
  using Node = TrieNode< char_size >;

  vector< Node > nodes;
  int root;

  Trie() : root(0) {
    nodes.push_back(Node());
  }

  void update_direct(int node, int id) {
    nodes[node].accept.push_back(id);
  }

  void update_child(int node, int child, int id) {
    ++nodes[node].exist;
  }

  void add(const string &str, int str_index, int node_index, int id) {
    if(str_index == str.size()) {
      update_direct(node_index, id);
    } else {
      const int c = str[str_index] - margin;
      if(nodes[node_index].nxt[c] == -1) {
        nodes[node_index].nxt[c] = (int) nodes.size();
        nodes.push_back(Node());
      }
      add(str, str_index + 1, nodes[node_index].nxt[c], id);
      update_child(node_index, nodes[node_index].nxt[c], id);
    }
  }

  void add(const string &str, int id) {
    add(str, 0, 0, id);
  }

  void add(const string &str) {
    add(str, nodes[0].exist);
  }

  void query(const string &str, const function< void(int) > &f, int str_index, int node_index) {
    for(auto &idx : nodes[node_index].accept) f(idx);
    if(str_index == str.size()) {
      return;
    } else {
      const int c = str[str_index] - margin;
      if(nodes[node_index].nxt[c] == -1) return;
      query(str, f, str_index + 1, nodes[node_index].nxt[c]);
    }
  }

  void query(const string &str, const function< void(int) > &f) {
    query(str, f, 0, 0);
  }

  int count() const {
    return (nodes[0].exist);
  }

  int size() const {
    return ((int) nodes.size());
  }
};
template< int char_size, int margin >
struct AhoCorasick : Trie< char_size + 1, margin > {
  using Trie< char_size + 1, margin >::Trie;

  const int FAIL = char_size;
  vector< int > correct;

  void build(bool heavy = true) {
    correct.resize(this->size());
    for(int i = 0; i < this->size(); i++) {
      correct[i] = (int) this->nodes[i].accept.size();
    }
    queue< int > que;
    for(int i = 0; i <= char_size; i++) {
      if(~this->nodes[0].nxt[i]) {
        this->nodes[this->nodes[0].nxt[i]].nxt[FAIL] = 0;
        que.emplace(this->nodes[0].nxt[i]);
      } else {
        this->nodes[0].nxt[i] = 0;
      }
    }
    while(!que.empty()) {
      auto &now = this->nodes[que.front()];
      correct[que.front()] += correct[now.nxt[FAIL]];
      que.pop();
      for(int i = 0; i < char_size; i++) {
        if(now.nxt[i] == -1) continue;
        int fail = now.nxt[FAIL];
        while(this->nodes[fail].nxt[i] == -1) fail = this->nodes[fail].nxt[FAIL];
        this->nodes[now.nxt[i]].nxt[FAIL] = this->nodes[fail].nxt[i];
        if(heavy) {
          auto &u = this->nodes[now.nxt[i]].accept;
          auto &v = this->nodes[this->nodes[fail].nxt[i]].accept;
          vector< int > accept;
          set_union(begin(u), end(u), begin(v), end(v), back_inserter(accept));
          u = accept;
        }
        que.emplace(now.nxt[i]);
      }

    }
  }

  map< int, int > match(const string &str, int now = 0) {
    map< int, int > result;
    for(auto &c : str) {
      while(this->nodes[now].nxt[c - margin] == -1) now = this->nodes[now].nxt[FAIL];
      now = this->nodes[now].nxt[c - margin];
      for(auto &v : this->nodes[now].accept) result[v] += 1;
    }
    return result;
  }

  pair< int, int > move(const char &c, int now) {
    int sum = 0;
    while(this->nodes[now].nxt[c - margin] == -1) now = this->nodes[now].nxt[FAIL];
    now = this->nodes[now].nxt[c - margin];
    sum += correct[now];
    return {sum, now};
  }
};
vector<int> g[400010];
char c[400010];
int n, m;
int k[400010];
AhoCorasick<26, 'a'> aho;
int cnt[400010];
map<int, vector<int>> mp;
void dfs(int x, int now){
	for(auto y:g[x]){
		P pr=aho.move(c[y], now);
		if(!aho.nodes[pr.second].accept.empty()) mp[pr.second].push_back(y);
		dfs(y, pr.second);
	}
}
vector<int> v1[400010]; vector<P> v2[400010];
int cnt1[400010];
void dfs1(int x){
	for(auto i:v1[x]){
		cnt1[i]++;
	}
	for(auto pr:v2[x]){
		cnt[pr.second]+=cnt1[pr.first];
	}
	for(auto y:g[x]) dfs1(y);
	for(auto i:v1[x]){
		cnt1[i]--;
	}
}
int main()
{
	cin>>n;
	for(int i=1; i<=n; i++){
		int t;
		cin>>t;
		if(t==1){
			cin>>c[i];
			g[0].push_back(i);
		}else{
			int j; cin>>j>>c[i];
			g[j].push_back(i);
		}
	}
	cin>>m;
	for(int i=0; i<m; i++){
		cin>>k[i];
		string t; cin>>t;
		aho.add(t, i);
	}
	aho.build();
	dfs(0, 0);
	int l=0;
	for(auto pr:mp){
		vector<int> v=pr.second, w=aho.nodes[pr.first].accept;
		for(auto x:v) v1[x].push_back(l);
		for(auto i:w) v2[k[i]].push_back({l, i});
		l++;
	}
	dfs1(0);
	for(int i=0; i<m; i++){
		printf("%d\n", cnt[i]);
	}
	return 0;
}


#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#include <cmath>
#include <bitset>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <algorithm>
#include <complex>
#include <unordered_map>
#include <unordered_set>
#include <random>
#include <cassert>
#include <fstream>
#include <utility>
#include <functional>
#define popcount __builtin_popcount
using namespace std;
typedef long long int ll;
typedef pair<int, int> P;
template< int char_size >
struct TrieNode {
  int nxt[char_size];

  int exist;
  vector< int > accept;

  TrieNode() : exist(0) {
    memset(nxt, -1, sizeof(nxt));
  }
};

template< int char_size, int margin >
struct Trie {
  using Node = TrieNode< char_size >;

  vector< Node > nodes;
  int root;

  Trie() : root(0) {
    nodes.push_back(Node());
  }

  void update_direct(int node, int id) {
    nodes[node].accept.push_back(id);
  }

  void update_child(int node, int child, int id) {
    ++nodes[node].exist;
  }

  void add(const string &str, int str_index, int node_index, int id) {
    if(str_index == str.size()) {
      update_direct(node_index, id);
    } else {
      const int c = str[str_index] - margin;
      if(nodes[node_index].nxt[c] == -1) {
        nodes[node_index].nxt[c] = (int) nodes.size();
        nodes.push_back(Node());
      }
      add(str, str_index + 1, nodes[node_index].nxt[c], id);
      update_child(node_index, nodes[node_index].nxt[c], id);
    }
  }

  void add(const string &str, int id) {
    add(str, 0, 0, id);
  }

  void add(const string &str) {
    add(str, nodes[0].exist);
  }

  void query(const string &str, const function< void(int) > &f, int str_index, int node_index) {
    for(auto &idx : nodes[node_index].accept) f(idx);
    if(str_index == str.size()) {
      return;
    } else {
      const int c = str[str_index] - margin;
      if(nodes[node_index].nxt[c] == -1) return;
      query(str, f, str_index + 1, nodes[node_index].nxt[c]);
    }
  }

  void query(const string &str, const function< void(int) > &f) {
    query(str, f, 0, 0);
  }

  int count() const {
    return (nodes[0].exist);
  }

  int size() const {
    return ((int) nodes.size());
  }
};
template< int char_size, int margin >
struct AhoCorasick : Trie< char_size + 1, margin > {
  using Trie< char_size + 1, margin >::Trie;

  const int FAIL = char_size;
  vector< int > correct;

  void build(bool heavy = true) {
    correct.resize(this->size());
    for(int i = 0; i < this->size(); i++) {
      correct[i] = (int) this->nodes[i].accept.size();
    }
    queue< int > que;
    for(int i = 0; i <= char_size; i++) {
      if(~this->nodes[0].nxt[i]) {
        this->nodes[this->nodes[0].nxt[i]].nxt[FAIL] = 0;
        que.emplace(this->nodes[0].nxt[i]);
      } else {
        this->nodes[0].nxt[i] = 0;
      }
    }
    while(!que.empty()) {
      auto &now = this->nodes[que.front()];
      correct[que.front()] += correct[now.nxt[FAIL]];
      que.pop();
      for(int i = 0; i < char_size; i++) {
        if(now.nxt[i] == -1) continue;
        int fail = now.nxt[FAIL];
        while(this->nodes[fail].nxt[i] == -1) fail = this->nodes[fail].nxt[FAIL];
        this->nodes[now.nxt[i]].nxt[FAIL] = this->nodes[fail].nxt[i];
        if(heavy) {
          auto &u = this->nodes[now.nxt[i]].accept;
          auto &v = this->nodes[this->nodes[fail].nxt[i]].accept;
          vector< int > accept;
          set_union(begin(u), end(u), begin(v), end(v), back_inserter(accept));
          u = accept;
        }
        que.emplace(now.nxt[i]);
      }

    }
  }

  map< int, int > match(const string &str, int now = 0) {
    map< int, int > result;
    for(auto &c : str) {
      while(this->nodes[now].nxt[c - margin] == -1) now = this->nodes[now].nxt[FAIL];
      now = this->nodes[now].nxt[c - margin];
      for(auto &v : this->nodes[now].accept) result[v] += 1;
    }
    return result;
  }

  pair< int, int > move(const char &c, int now) {
    int sum = 0;
    while(this->nodes[now].nxt[c - margin] == -1) now = this->nodes[now].nxt[FAIL];
    now = this->nodes[now].nxt[c - margin];
    sum += correct[now];
    return {sum, now};
  }
};
vector<int> g[400010];
char c[400010];
int n, m;
int k[400010];
AhoCorasick<26, 'a'> aho;
vector<int> v[400010];
int cnt[400010];
int d[400002];
int p[19][400002];
bool used[400002];
void dfs0(int x){
	for(auto y:g[x]){
		d[y]=d[x]+1;
		p[0][y]=x;
		dfs0(y);
	}
}
void init_lca(){
	dfs0(0);
	for(int i=1; i<19; i++){
        for(int x=0; x<n+1; x++){
            p[i][x]=p[i-1][p[i-1][x]];
        }
    }
}
int lca(int a, int b){
	if(d[a]>d[b]) swap(a, b);
    int a1=a, b1=b;
    int dd=d[b]-d[a], i=0;
    while(dd>0){
        if(dd%2==1){
            b1=p[i][b1];
        }
        dd/=2;
        i++;
    }
    if(a1==b1) return a1;
    for(int i=18; i>=0; i--){
        if(p[i][a1]!=p[i][b1]){
            a1=p[i][a1], b1=p[i][b1];
        }
    }
    return p[0][a1];
}
void dfs(int x, int now){
	for(auto y:g[x]){
		P pr=aho.move(c[y], now);
		for(auto i:aho.nodes[pr.second].accept){
			if(lca(y, k[i])==y) cnt[i]++;
		}
		dfs(y, pr.second);
	}
}
int main()
{
	cin>>n;
	for(int i=1; i<=n; i++){
		int t;
		cin>>t;
		if(t==1){
			cin>>c[i];
			g[0].push_back(i);
		}else{
			int j; cin>>j>>c[i];
			g[j].push_back(i);
		}
	}
	cin>>m;
	for(int i=0; i<m; i++){
		cin>>k[i];
		string t; cin>>t;
		aho.add(t, i);
	}
	aho.build();
	init_lca();
	dfs(0, 0);
	for(int i=0; i<m; i++){
		printf("%d\n", cnt[i]);
	}
	return 0;
}


#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#include <cmath>
#include <bitset>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <algorithm>
#include <complex>
#include <unordered_map>
#include <unordered_set>
#include <random>
#include <cassert>
#include <fstream>
#include <utility>
#include <functional>
#define popcount __builtin_popcount
using namespace std;
typedef long long int ll;
typedef pair<int, int> P;
template< int char_size >
struct TrieNode {
  int nxt[char_size];

  int exist;
  vector< int > accept;

  TrieNode() : exist(0) {
    memset(nxt, -1, sizeof(nxt));
  }
};

template< int char_size, int margin >
struct Trie {
  using Node = TrieNode< char_size >;

  vector< Node > nodes;
  int root;

  Trie() : root(0) {
    nodes.push_back(Node());
  }

  void update_direct(int node, int id) {
    nodes[node].accept.push_back(id);
  }

  void update_child(int node, int child, int id) {
    ++nodes[node].exist;
  }

  void add(const string &str, int str_index, int node_index, int id) {
    if(str_index == str.size()) {
      update_direct(node_index, id);
    } else {
      const int c = str[str_index] - margin;
      if(nodes[node_index].nxt[c] == -1) {
        nodes[node_index].nxt[c] = (int) nodes.size();
        nodes.push_back(Node());
      }
      add(str, str_index + 1, nodes[node_index].nxt[c], id);
      update_child(node_index, nodes[node_index].nxt[c], id);
    }
  }

  void add(const string &str, int id) {
    add(str, 0, 0, id);
  }

  void add(const string &str) {
    add(str, nodes[0].exist);
  }

  void query(const string &str, const function< void(int) > &f, int str_index, int node_index) {
    for(auto &idx : nodes[node_index].accept) f(idx);
    if(str_index == str.size()) {
      return;
    } else {
      const int c = str[str_index] - margin;
      if(nodes[node_index].nxt[c] == -1) return;
      query(str, f, str_index + 1, nodes[node_index].nxt[c]);
    }
  }

  void query(const string &str, const function< void(int) > &f) {
    query(str, f, 0, 0);
  }

  int count() const {
    return (nodes[0].exist);
  }

  int size() const {
    return ((int) nodes.size());
  }
};
template< int char_size, int margin >
struct AhoCorasick : Trie< char_size + 1, margin > {
  using Trie< char_size + 1, margin >::Trie;

  const int FAIL = char_size;
  vector< int > correct;

  void build(bool heavy = true) {
    correct.resize(this->size());
    for(int i = 0; i < this->size(); i++) {
      correct[i] = (int) this->nodes[i].accept.size();
    }
    queue< int > que;
    for(int i = 0; i <= char_size; i++) {
      if(~this->nodes[0].nxt[i]) {
        this->nodes[this->nodes[0].nxt[i]].nxt[FAIL] = 0;
        que.emplace(this->nodes[0].nxt[i]);
      } else {
        this->nodes[0].nxt[i] = 0;
      }
    }
    while(!que.empty()) {
      auto &now = this->nodes[que.front()];
      correct[que.front()] += correct[now.nxt[FAIL]];
      que.pop();
      for(int i = 0; i < char_size; i++) {
        if(now.nxt[i] == -1) continue;
        int fail = now.nxt[FAIL];
        while(this->nodes[fail].nxt[i] == -1) fail = this->nodes[fail].nxt[FAIL];
        this->nodes[now.nxt[i]].nxt[FAIL] = this->nodes[fail].nxt[i];
        if(heavy) {
          auto &u = this->nodes[now.nxt[i]].accept;
          auto &v = this->nodes[this->nodes[fail].nxt[i]].accept;
          vector< int > accept;
          set_union(begin(u), end(u), begin(v), end(v), back_inserter(accept));
          u = accept;
        }
        que.emplace(now.nxt[i]);
      }

    }
  }

  map< int, int > match(const string &str, int now = 0) {
    map< int, int > result;
    for(auto &c : str) {
      while(this->nodes[now].nxt[c - margin] == -1) now = this->nodes[now].nxt[FAIL];
      now = this->nodes[now].nxt[c - margin];
      for(auto &v : this->nodes[now].accept) result[v] += 1;
    }
    return result;
  }

  pair< int, int > move(const char &c, int now) {
    int sum = 0;
    while(this->nodes[now].nxt[c - margin] == -1) now = this->nodes[now].nxt[FAIL];
    now = this->nodes[now].nxt[c - margin];
    sum += correct[now];
    return {sum, now};
  }
};
vector<int> g[400010];
char c[400010];
int n, m;
int k[400010];
AhoCorasick<26, 'a'> aho;
int cnt[400010];
int d[400002];
int p[19][400002];
bool used[400002];
void dfs0(int x){
	for(auto y:g[x]){
		d[y]=d[x]+1;
		p[0][y]=x;
		dfs0(y);
	}
}
void init_lca(){
	dfs0(0);
	for(int i=1; i<19; i++){
        for(int x=0; x<n+1; x++){
            p[i][x]=p[i-1][p[i-1][x]];
        }
    }
}
int lca(int a, int b){
	if(d[a]>d[b]) swap(a, b);
    int a1=a, b1=b;
    int dd=d[b]-d[a], i=0;
    while(dd>0){
        if(dd%2==1){
            b1=p[i][b1];
        }
        dd/=2;
        i++;
    }
    if(a1==b1) return a1;
    for(int i=18; i>=0; i--){
        if(p[i][a1]!=p[i][b1]){
            a1=p[i][a1], b1=p[i][b1];
        }
    }
    return p[0][a1];
}
map<int, vector<int>> mp;
void dfs(int x, int now){
	for(auto y:g[x]){
		P pr=aho.move(c[y], now);
		mp[pr.second].push_back(y);
		dfs(y, pr.second);
	}
}
vector<int> v1[400010]; vector<P> v2[400010];
int cnt1[400010];
void dfs1(int x){
	for(auto i:v1[x]){
		cnt1[i]++;
	}
	for(auto pr:v2[x]){
		cnt[pr.second]+=cnt1[pr.first];
	}
	for(auto y:g[x]) dfs1(y);
	for(auto i:v1[x]){
		cnt1[i]--;
	}
}
int main()
{
	cin>>n;
	for(int i=1; i<=n; i++){
		int t;
		cin>>t;
		if(t==1){
			cin>>c[i];
			g[0].push_back(i);
		}else{
			int j; cin>>j>>c[i];
			g[j].push_back(i);
		}
	}
	cin>>m;
	for(int i=0; i<m; i++){
		cin>>k[i];
		string t; cin>>t;
		aho.add(t, i);
	}
	aho.build();
	init_lca();
	dfs(0, 0);
	int l=0;
	for(auto pr:mp){
		vector<int> v=pr.second, w=aho.nodes[pr.first].accept;
		for(auto x:v) v1[x].push_back(l);
		for(auto i:w) v2[k[i]].push_back({l, i});
		l++;
	}
	dfs1(0);
	for(int i=0; i<m; i++){
		printf("%d\n", cnt[i]);
	}
	return 0;
}


#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#include <cmath>
#include <bitset>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <algorithm>
#include <complex>
#include <unordered_map>
#include <unordered_set>
#include <random>
#include <cassert>
#include <fstream>
#include <utility>
#include <functional>
#define popcount __builtin_popcount
using namespace std;
typedef long long int ll;
typedef pair<int, int> P;
template< int char_size >
struct TrieNode {
  int nxt[char_size];

  int exist;
  vector< int > accept;

  TrieNode() : exist(0) {
    memset(nxt, -1, sizeof(nxt));
  }
};

template< int char_size, int margin >
struct Trie {
  using Node = TrieNode< char_size >;

  vector< Node > nodes;
  int root;

  Trie() : root(0) {
    nodes.push_back(Node());
  }

  void update_direct(int node, int id) {
    nodes[node].accept.push_back(id);
  }

  void update_child(int node, int child, int id) {
    ++nodes[node].exist;
  }

  void add(const string &str, int str_index, int node_index, int id) {
    if(str_index == str.size()) {
      update_direct(node_index, id);
    } else {
      const int c = str[str_index] - margin;
      if(nodes[node_index].nxt[c] == -1) {
        nodes[node_index].nxt[c] = (int) nodes.size();
        nodes.push_back(Node());
      }
      add(str, str_index + 1, nodes[node_index].nxt[c], id);
      update_child(node_index, nodes[node_index].nxt[c], id);
    }
  }

  void add(const string &str, int id) {
    add(str, 0, 0, id);
  }

  void add(const string &str) {
    add(str, nodes[0].exist);
  }

  void query(const string &str, const function< void(int) > &f, int str_index, int node_index) {
    for(auto &idx : nodes[node_index].accept) f(idx);
    if(str_index == str.size()) {
      return;
    } else {
      const int c = str[str_index] - margin;
      if(nodes[node_index].nxt[c] == -1) return;
      query(str, f, str_index + 1, nodes[node_index].nxt[c]);
    }
  }

  void query(const string &str, const function< void(int) > &f) {
    query(str, f, 0, 0);
  }

  int count() const {
    return (nodes[0].exist);
  }

  int size() const {
    return ((int) nodes.size());
  }
};
template< int char_size, int margin >
struct AhoCorasick : Trie< char_size + 1, margin > {
  using Trie< char_size + 1, margin >::Trie;

  const int FAIL = char_size;
  vector< int > correct;

  void build(bool heavy = true) {
    correct.resize(this->size());
    for(int i = 0; i < this->size(); i++) {
      correct[i] = (int) this->nodes[i].accept.size();
    }
    queue< int > que;
    for(int i = 0; i <= char_size; i++) {
      if(~this->nodes[0].nxt[i]) {
        this->nodes[this->nodes[0].nxt[i]].nxt[FAIL] = 0;
        que.emplace(this->nodes[0].nxt[i]);
      } else {
        this->nodes[0].nxt[i] = 0;
      }
    }
    while(!que.empty()) {
      auto &now = this->nodes[que.front()];
      correct[que.front()] += correct[now.nxt[FAIL]];
      que.pop();
      for(int i = 0; i < char_size; i++) {
        if(now.nxt[i] == -1) continue;
        int fail = now.nxt[FAIL];
        while(this->nodes[fail].nxt[i] == -1) fail = this->nodes[fail].nxt[FAIL];
        this->nodes[now.nxt[i]].nxt[FAIL] = this->nodes[fail].nxt[i];
        if(heavy) {
          auto &u = this->nodes[now.nxt[i]].accept;
          auto &v = this->nodes[this->nodes[fail].nxt[i]].accept;
          vector< int > accept;
          set_union(begin(u), end(u), begin(v), end(v), back_inserter(accept));
          u = accept;
        }
        que.emplace(now.nxt[i]);
      }

    }
  }

  map< int, int > match(const string &str, int now = 0) {
    map< int, int > result;
    for(auto &c : str) {
      while(this->nodes[now].nxt[c - margin] == -1) now = this->nodes[now].nxt[FAIL];
      now = this->nodes[now].nxt[c - margin];
      for(auto &v : this->nodes[now].accept) result[v] += 1;
    }
    return result;
  }

  pair< int, int > move(const char &c, int now) {
    int sum = 0;
    while(this->nodes[now].nxt[c - margin] == -1) now = this->nodes[now].nxt[FAIL];
    now = this->nodes[now].nxt[c - margin];
    sum += correct[now];
    return {sum, now};
  }
};
vector<int> g[400010];
char c[400010];
int n, m;
int k[400010];
AhoCorasick<26, 'a'> aho;
vector<int> v[400010];
int cnt[400010];
int d[400002];
int p[19][400002];
bool used[400002];
void dfs0(int x){
	for(auto y:g[x]){
		d[y]=d[x]+1;
		p[0][y]=x;
		dfs0(y);
	}
}
void init_lca(){
	dfs0(0);
	for(int i=1; i<19; i++){
        for(int x=0; x<n+1; x++){
            p[i][x]=p[i-1][p[i-1][x]];
        }
    }
}
int lca(int a, int b){
	if(d[a]>d[b]) swap(a, b);
    int a1=a, b1=b;
    int dd=d[b]-d[a], i=0;
    while(dd>0){
        if(dd%2==1){
            b1=p[i][b1];
        }
        dd/=2;
        i++;
    }
    if(a1==b1) return a1;
    for(int i=18; i>=0; i--){
        if(p[i][a1]!=p[i][b1]){
            a1=p[i][a1], b1=p[i][b1];
        }
    }
    return p[0][a1];
}
void dfs(int x, int now){
	for(auto y:g[x]){
		P pr=aho.move(c[y], now);
		for(auto i:aho.nodes[pr.second].accept){
			if(lca(y, k[i])==y) cnt[i]++;
		}
		dfs(y, pr.second);
	}
}
int main()
{
	cin>>n;
	for(int i=1; i<=n; i++){
		int t;
		cin>>t;
		if(t==1){
			cin>>c[i];
			g[0].push_back(i);
		}else{
			int j; cin>>j>>c[i];
			g[j].push_back(i);
		}
	}
	cin>>m;
	for(int i=0; i<m; i++){
		cin>>k[i];
		string t; cin>>t;
		aho.add(t, i);
	}
	aho.build();
	init_lca();
	dfs(0, 0);
	for(int i=0; i<m; i++){
		cout<<cnt[i]<<endl;
	}
	return 0;
}


#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#include <cmath>
#include <bitset>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <algorithm>
#include <complex>
#include <unordered_map>
#include <unordered_set>
#include <random>
#include <cassert>
#include <fstream>
#include <utility>
#include <functional>
#define popcount __builtin_popcount
using namespace std;
typedef long long int ll;
typedef pair<int, int> P;
template< int char_size >
struct TrieNode {
  int nxt[char_size];

  int exist;
  vector< int > accept;

  TrieNode() : exist(0) {
    memset(nxt, -1, sizeof(nxt));
  }
};

template< int char_size, int margin >
struct Trie {
  using Node = TrieNode< char_size >;

  vector< Node > nodes;
  int root;

  Trie() : root(0) {
    nodes.push_back(Node());
  }

  void update_direct(int node, int id) {
	  if(nodes[node].accept.empty()) nodes[node].accept.emplace_back(node);
    //nodes[node].accept.push_back(id);
  }

  void update_child(int node, int child, int id) {
    ++nodes[node].exist;
  }

  //void add(const string &str, int str_index, int node_index, int id) {
  int add(const string &str, int str_index, int node_index, int id) {
    if(str_index == str.size()) {
      update_direct(node_index, id);
	  return node_index;
    } else {
      const int c = str[str_index] - margin;
      if(nodes[node_index].nxt[c] == -1) {
        nodes[node_index].nxt[c] = (int) nodes.size();
        nodes.push_back(Node());
      }
      int idx=add(str, str_index + 1, nodes[node_index].nxt[c], id);
      update_child(node_index, nodes[node_index].nxt[c], id);
	  return idx;
    }
  }

  //void add(const string &str, int id) {
  int add(const string &str, int id) {
    return add(str, 0, 0, id);
  }

  void add(const string &str) {
    add(str, nodes[0].exist);
  }

  void query(const string &str, const function< void(int) > &f, int str_index, int node_index) {
    for(auto &idx : nodes[node_index].accept) f(idx);
    if(str_index == str.size()) {
      return;
    } else {
      const int c = str[str_index] - margin;
      if(nodes[node_index].nxt[c] == -1) return;
      query(str, f, str_index + 1, nodes[node_index].nxt[c]);
    }
  }

  void query(const string &str, const function< void(int) > &f) {
    query(str, f, 0, 0);
  }

  int count() const {
    return (nodes[0].exist);
  }

  int size() const {
    return ((int) nodes.size());
  }
};
template< int char_size, int margin >
struct AhoCorasick : Trie< char_size + 1, margin > {
  using Trie< char_size + 1, margin >::Trie;

  const int FAIL = char_size;
  vector< int > correct;

  void build(bool heavy = true) {
    correct.resize(this->size());
    for(int i = 0; i < this->size(); i++) {
      correct[i] = (int) this->nodes[i].accept.size();
    }
    queue< int > que;
    for(int i = 0; i <= char_size; i++) {
      if(~this->nodes[0].nxt[i]) {
        this->nodes[this->nodes[0].nxt[i]].nxt[FAIL] = 0;
        que.emplace(this->nodes[0].nxt[i]);
      } else {
        this->nodes[0].nxt[i] = 0;
      }
    }
    while(!que.empty()) {
      auto &now = this->nodes[que.front()];
      correct[que.front()] += correct[now.nxt[FAIL]];
      que.pop();
      for(int i = 0; i < char_size; i++) {
        if(now.nxt[i] == -1) continue;
        int fail = now.nxt[FAIL];
        while(this->nodes[fail].nxt[i] == -1) fail = this->nodes[fail].nxt[FAIL];
        this->nodes[now.nxt[i]].nxt[FAIL] = this->nodes[fail].nxt[i];
        if(heavy) {
          auto &u = this->nodes[now.nxt[i]].accept;
          auto &v = this->nodes[this->nodes[fail].nxt[i]].accept;
          vector< int > accept;
          set_union(begin(u), end(u), begin(v), end(v), back_inserter(accept));
          u = accept;
        }
        que.emplace(now.nxt[i]);
      }

    }
  }

  map< int, int > match(const string &str, int now = 0) {
    map< int, int > result;
    for(auto &c : str) {
      while(this->nodes[now].nxt[c - margin] == -1) now = this->nodes[now].nxt[FAIL];
      now = this->nodes[now].nxt[c - margin];
      for(auto &v : this->nodes[now].accept) result[v] += 1;
    }
    return result;
  }

  pair< int, int > move(const char &c, int now) {
    int sum = 0;
    while(this->nodes[now].nxt[c - margin] == -1) now = this->nodes[now].nxt[FAIL];
    now = this->nodes[now].nxt[c - margin];
    sum += correct[now];
    return {sum, now};
  }
};
vector<int> g[400010];
char c[400010];
int n, m;
int k[400010];
AhoCorasick<26, 'a'> aho;
int cnt[400010];
vector<int> vk[400010];
int qi[400010];
int cnt1[400010];
void dfs(int x, int now){
	for(auto i:vk[x]) cnt[i]=cnt1[qi[i]];
	for(auto y:g[x]){
		int nx=aho.move(c[y], now).second;
		for(auto i:aho.nodes[nx].accept) cnt1[i]++;
		dfs(y, nx);
		for(auto i:aho.nodes[nx].accept) cnt1[i]--;
	}
}
int main()
{
	cin>>n;
	for(int i=1; i<=n; i++){
		int t;
		cin>>t;
		if(t==1){
			cin>>c[i];
			g[0].push_back(i);
		}else{
			int j; cin>>j>>c[i];
			g[j].push_back(i);
		}
	}
	cin>>m;
	for(int i=0; i<m; i++){
		cin>>k[i];
		string t; cin>>t;
		qi[i]=aho.add(t, i);
		vk[k[i]].push_back(i);
	}
	aho.build();
	dfs(0, 0);
	for(int i=0; i<m; i++){
		printf("%d\n", cnt[i]);
	}
	return 0;
}


//              +-- -- --++-- +-In the name of ALLAH-+ --++-- -- --+              \\

#include <bits/stdc++.h>

#define F first
#define S second
#define _sz(x) (int)x.size()
#define pb push_back

#define error(x) cout << #x << " = " << x << endl

using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;

const int N = 4e5 + 20, AL = 26;
int n, m;
int snxt[N][AL], ss, plc[N];
int qnxt[N][AL], sq, f[N], up[N];
bool mark[N];
vector <pii> qs[N];

inline void aho ()
{
	queue <int> que;

	for (int i = 0; i < AL; i++)
		if (qnxt[0][i]) que.push(qnxt[0][i]);

	while (_sz(que))
	{
		int v = que.front();
		que.pop();

		up[v] = (mark[f[v]] ? f[v] : up[f[v]]);

		for (int i = 0; i < AL; i++)
		{
			if (!qnxt[v][i])
				qnxt[v][i] = qnxt[f[v]][i];
			else
			{
				f[qnxt[v][i]] = qnxt[f[v]][i];
				que.push(qnxt[v][i]);
			}
		}
	}
}

int val[N];
int res[N];

inline void add (int v, int x)
{
	while (v)
	{
		val[v] += x;
		v = up[v];
	}
}

void dfs (int sstate, int qstate)
{
	add(qstate, 1);

	for (pii p : qs[sstate])
		res[p.S] = val[p.F];

	for (int i = 0; i < AL; i++)
		if (snxt[sstate][i])
			dfs(snxt[sstate][i], qnxt[qstate][i]);

	add(qstate, -1);
}

int main()
{
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);

	cin >> n;

	for (int i = 0; i < n; i++)
	{
		int type;
		cin >> type;

		int s = 0;
		if (type == 2)
		{
			int p;
			cin >> p;
			p--;
			s = plc[p];
		}

		char c;
		cin >> c;
		c -= 'a';

		if (!snxt[s][c]) snxt[s][c] = ++ss;

		s = snxt[s][c];
		plc[i] = s;
	}

	cin >> m;

	for (int i = 0; i < m; i++)
	{
		int p;
		string s;

		cin >> p >> s;
		p--;

		int cur = 0;

		for (int j = 0; j < _sz(s); j++)
		{
			int c = s[j] - 'a';
			if (!qnxt[cur][c]) qnxt[cur][c] = ++sq;

			cur = qnxt[cur][c];
		}

		mark[cur] = 1;

		qs[plc[p]].pb({cur, i});
	}

	aho();

	dfs(0, 0);

	for (int i = 0; i < m; i++) cout << res[i] << '\n';
}


//              +-- -- --++-- +-In the name of ALLAH-+ --++-- -- --+              \\

#include <bits/stdc++.h>

#define F first
#define S second
#define _sz(x) (int)x.size()
#define pb push_back

#define error(x) cout << #x << " = " << x << endl

using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;

const int N = 4e5 + 20, AL = 26;
int n, m;
int snxt[N][AL], ss, plc[N];
int qnxt[N][AL], sq, f[N];
bool mark[N];
vector <pii> qs[N];

vector <int> g[N];

inline void aho ()
{
	queue <int> que;

	for (int i = 0; i < AL; i++)
		if (qnxt[0][i]) que.push(qnxt[0][i]);

	while (_sz(que))
	{
		int v = que.front();
		que.pop();

		g[f[v]].pb(v);

		for (int i = 0; i < AL; i++)
		{
			if (!qnxt[v][i])
				qnxt[v][i] = qnxt[f[v]][i];
			else
			{
				f[qnxt[v][i]] = qnxt[f[v]][i];
				que.push(qnxt[v][i]);
			}
		}
	}
}

int fen[N];

inline void add (int p, int val)
{
	for (p++; p < N; p += p & -p) fen[p] += val;
}

inline int get (int p)
{
	int sum = 0;
	for (; p; p -= p & -p) sum += fen[p];
	return sum;
}

inline int get (int l, int r)
{
	return get(r) - get(l);
}

int st[N], ft[N];
int res[N];

void dfs (int sstate, int qstate)
{
	add(st[qstate], 1);

	for (pii p : qs[sstate])
		res[p.S] = get(st[p.F], ft[p.F]);

	for (int i = 0; i < AL; i++)
		if (snxt[sstate][i])
			dfs(snxt[sstate][i], qnxt[qstate][i]);

	add(st[qstate], -1);
}

void pre_dfs (int qstate)
{
	static int tme = 0;
	st[qstate] = tme++;

	for (int ns : g[qstate])
		pre_dfs(ns);

	ft[qstate] = tme;
}

int main()
{
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);

	cin >> n;

	for (int i = 0; i < n; i++)
	{
		int type;
		cin >> type;

		int s = 0;
		if (type == 2)
		{
			int p;
			cin >> p;
			p--;
			s = plc[p];
		}

		char c;
		cin >> c;
		c -= 'a';

		if (!snxt[s][c]) snxt[s][c] = ++ss;

		s = snxt[s][c];
		plc[i] = s;
	}

	cin >> m;

	for (int i = 0; i < m; i++)
	{
		int p;
		string s;

		cin >> p >> s;
		p--;

		int cur = 0;

		for (int j = 0; j < _sz(s); j++)
		{
			int c = s[j] - 'a';
			if (!qnxt[cur][c]) qnxt[cur][c] = ++sq;

			cur = qnxt[cur][c];
		}

		mark[cur] = 1;

		qs[plc[p]].pb({cur, i});
	}

	aho();

	pre_dfs(0);

	dfs(0, 0);

	for (int i = 0; i < m; i++) cout << res[i] << '\n';
}


#include <bits/stdc++.h>

using namespace std;

const int MAXN = 400005;
const int K = 26;

struct BIT {
private:
    vector<int> t;
public:
    BIT(int n) {t.assign(n+1, 0);}

    void update(int p, int x) {
        for(int i = p; i < t.size(); i += i & (-i))
            t[i] += x;
    }

    int query(int p) {
        int res = 0;
        for(int i = p; i > 0; i -= i & (-i))
            res += t[i];
        return res;
    }
};

struct Vertex {
    int nxt[K];
    int p;
    char pch;
    int go[K];
    int link = -1;
    int leaf = -1;

    Vertex(int p = -1, char ch = '$'): p(p), pch(ch) {
        fill(begin(nxt), end(nxt), -1);
        fill(begin(go), end(go), -1);
    }
};

int n, m, in[MAXN], out[MAXN], dfs_cnt, ans[MAXN];
vector<pair<int, char>> g[MAXN];
vector<int> linkG[MAXN];
vector<Vertex> t(1);
vector<pair<int, int>> query[MAXN];

int add_string(string s, int ind) {
    int v = 0;
    for(char ch: s) {
        int c = ch-'a';
        if (t[v].nxt[c] == -1) {
            t[v].nxt[c] = t.size();
            t.push_back(Vertex(v, c));
        }
        v = t[v].nxt[c];
    }
    t[v].leaf = ind;
    return v;
}

int go(int v, int c);

int get_link(int v) {
    int &res = t[v].link;
    if (res == -1) {
        if (v == 0 || t[v].p == 0) res = 0;
        else res = go(get_link(t[v].p), t[v].pch);
    }
    return res;
}

int go(int v, int c) {
    int &res = t[v].go[c];
    if (res == -1) {
        if (t[v].nxt[c] != -1) res = t[v].nxt[c];
        else if (v == 0) res = 0;
        else res = go(get_link(v), c);
    }
    return res;
}

void dfs_link(int u) {
    in[u] = ++dfs_cnt;
    for(int v: linkG[u])
        dfs_link(v);
    out[u] = dfs_cnt;
}

void dfs_g(int u, int at_u, BIT &bit) {
    for(pair<int, int> p: query[u])
        ans[p.first] = bit.query(out[p.second]) - bit.query(in[p.second] - 1);

    for(auto e: g[u]) {
        int v = e.first;
        int c = e.second - 'a';
        int at_v = go(at_u, c);

        bit.update(in[at_v], 1);
        dfs_g(v, at_v, bit);
        bit.update(in[at_v], -1);
    }
}

int main() {
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i) {
        int t, j;
        char c;
        scanf("%d", &t);
        if (t == 1) {
            scanf(" %c", &c);
            g[0].push_back({i, c});
        } else {
            scanf("%d %c", &j, &c);
            g[j].push_back({i, c});
        }
    }

    scanf("%d", &m);
    for(int i = 0; i < m; ++i) {
        int u;
        string s;
        cin >> u >> s;
        query[u].push_back({i, add_string(s, i)});
    }

    for(int i = 1; i < t.size(); ++i)
        linkG[get_link(i)].push_back(i);

    dfs_link(0);

    BIT bit(t.size());
    dfs_g(0, 0, bit);

    for(int i = 0; i < m; ++i)
        printf("%d\n", ans[i]);

    return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int MAXN = 400005;

const int K = 26;

struct BIT {
private:
    vector<int> t;
public:
    BIT(int n) {t.assign(n+1, 0);}

    void update(int p, int x) {
        for(int i = p; i < t.size(); i += i & (-i))
            t[i] += x;
    }

    int query(int p) {
        int res = 0;
        for(int i = p; i > 0; i -= i & (-i))
            res += t[i];
        return res;
    }
};

struct Vertex {
    int nxt[K];
    int p;
    char pch;
    int go[K];
    int link = -1;
    int exit = -1;
    int leaf = -1;

    Vertex(int p = -1, char ch = '$'): p(p), pch(ch) {
        fill(begin(nxt), end(nxt), -1);
        fill(begin(go), end(go), -1);
    }
};

int n, m, s, in[MAXN], out[MAXN], dfs_cnt, ind_in_at[MAXN], ans[MAXN];
vector<pair<int, char>> g[MAXN];
vector<int> linkG[MAXN];
vector<Vertex> t(1);
vector<pair<int, int>> query[MAXN];

int add_string(string s, int ind) {
    int v = 0;
    for(char ch: s) {
        int c = ch-'a';
        if (t[v].nxt[c] == -1) {
            t[v].nxt[c] = t.size();
            t.push_back(Vertex(v, c));
        }
        v = t[v].nxt[c];
    }
    if (t[v].leaf == -1) {
        t[v].leaf = ind;
        ind_in_at[ind] = v;
    }
    return v;
}

int go(int v, int c);

int get_link(int v) {
    int &res = t[v].link;
    if (res == -1) {
        if (v == 0 || t[v].p == 0) res = 0;
        else res = go(get_link(t[v].p), t[v].pch);
    }
    return res;
}

int go(int v, int c) {
    int &res = t[v].go[c];
    if (res == -1) {
        if (t[v].nxt[c] != -1) res = t[v].nxt[c];
        else if (v == 0) res = 0;
        else res = go(get_link(v), c);
    }
    return res;
}

int get_exit(int v) {
    int &res = t[v].exit;
    if (res == -1) {
        if (t[v].leaf != -1) res = v;
        else if (v == 0 || t[v].p == 0) res = 0;
        else res = get_exit(get_link(v));
    }
    return res;
}

void dfs_link(int u) {
    in[u] = ++dfs_cnt;
    for(int v: linkG[u])
        dfs_link(v);
    out[u] = dfs_cnt;
}

void dfs_g(int u, int at_u, BIT &bit) {
    for(pair<int, int> p: query[u])
        ans[p.first] = bit.query(out[p.second]) - bit.query(in[p.second] - 1);

    for(auto e: g[u]) {
        int v = e.first;
        int c = e.second - 'a';
        int at_v = go(at_u, c);
//        printf("%d %d %d %d\n", u, at_u, v, at_v);

        bit.update(in[at_v], 1);
        dfs_g(v, at_v, bit);
        bit.update(in[at_v], -1);
    }
}

int main() {
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i) {
        int t, j;
        char c;
        scanf("%d", &t);
        if (t == 1) {
            scanf(" %c", &c);
            g[0].push_back({i, c});
        } else {
            scanf("%d %c", &j, &c);
            g[j].push_back({i, c});
        }
    }

    scanf("%d", &m);
    for(int i = 0; i < m; ++i) {
        int u;
        string s;
        cin >> u >> s;
        query[u].push_back({i, add_string(s, i)});
    }

//    for(int u = 1; u <= n; ++u) {
//        printf("u: %d\n", u);
//        for(pair<int, int> p: query[u])
//            printf("%d %d\n", p.first, p.second);
//    }

    for(int i = 1; i < t.size(); ++i) {
        linkG[get_link(i)].push_back(i);

//        printf("%d %d %d %d\n", i, t[i].leaf, get_link(i), get_exit(i));
    }

    dfs_link(0);

    BIT bit(t.size());
    dfs_g(0, 0, bit);

    for(int i = 0; i < m; ++i)
        printf("%d\n", ans[i]);

    return 0;
}


#include<bits/stdc++.h>
using namespace std;

template <class F>
struct y_combinator {
    F f; // the lambda will be stored here

    // a forwarding operator():
    template <class... Args> decltype(auto) operator()(Args&&... args) const {
        return f(std::ref(*this), std::forward<Args>(args)...);
    }
};

// helper function that deduces the type of the lambda:
template <class F> y_combinator<std::decay_t<F>> make_y_combinator(F&& f) {
    return {std::forward<F>(f)};
}

const int MAXN = 4.1e5;
int N;
int ind[MAXN];

const int MAXNODE = MAXN;
int NODE = 1;
int ch[MAXNODE][26];

//string trie_path[MAXNODE];

const int MAXM = 4.1e5;
int M;
int ans[MAXM];

const int MAXAH = 4.1e5;
int AH = 1;
int ah_ch[MAXAH][26];
//string ah_path[MAXAH];
int ah_fail[MAXAH];
vector<int> ah_fail_ch[MAXAH];
int ah_st[MAXAH];
int ah_en[MAXAH];

vector<pair<int, int>> queries[MAXNODE];

const int S = 1 << 19;
int seg[2 * S];

int main() {
    ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> N;
    for (int i = 1; i <= N; i++) {
        int t; cin >> t;
        int j;
        if (t == 1) {
            j = 0;
        } else {
            cin >> j;
        }
        char c; cin >> c;
        int node = ind[j];
        if (!ch[node][c-'a']) {
            ch[node][c-'a'] = NODE;
            //trie_path[NODE] = trie_path[node] + c;
            NODE++;
        }
        ind[i] = ch[node][c-'a'];
    }

    cin >> M;
    for (int q = 0; q < M; q++) {
        int i; string t; cin >> i >> t;
        int node = ind[i];
        int cur = 0;
        for (char c : t) {
            if (!ah_ch[cur][c-'a']) {
                ah_ch[cur][c-'a'] = AH;
                //ah_path[AH] = ah_path[cur] + c;
                AH++;
            }
            cur = ah_ch[cur][c-'a'];
        }

        queries[node].emplace_back(cur, q);
    }

    vector<int> ah_queue({0});
    ah_queue.reserve(AH);
    ah_fail[0] = -1;
    for (int z = 0; z < int(ah_queue.size()); z++) {
        int cur = ah_queue[z];
        //if (cur) cerr << "AH " << ah_path[cur] << ' ' << ah_path[ah_fail[cur]] << '\n';
        for (int c = 0; c < 26; c++) {
            int nxt = ah_ch[cur][c];
            int nxt_fail = ah_fail[cur] == -1 ? 0 : ah_ch[ah_fail[cur]][c];
            if (!nxt) {
                ah_ch[cur][c] = nxt_fail;
                continue;
            }
            ah_queue.push_back(nxt);
            ah_fail[nxt] = nxt_fail;
            ah_fail_ch[ah_fail[nxt]].push_back(nxt);
        }
    }

    {
        int incr = 0;
        make_y_combinator([&](auto dfs_preorder, int cur) -> void {
            ah_st[cur] = incr;
            ++incr;
            for (int nxt : ah_fail_ch[cur]) {
                dfs_preorder(nxt);
            }
            ah_en[cur] = incr;
        })(0);
    }

    {
        make_y_combinator([&](auto dfs_trie, int cur, int state) -> void {
            //cerr << "cur " << trie_path[cur] << ' ' << "state " << ah_path[state] << '\n';
            for (int a = S+ah_st[state]; a; a /= 2) {
                seg[a] ++;
            }
            for (auto it : queries[cur]) {
                int v = 0;
                for (int l = S+ah_st[it.first], r = S+ah_en[it.first]; l < r; l /= 2, r /= 2) {
                    if (l & 1) {
                        v += seg[l];
                        l++;
                    }
                    if (r & 1) {
                        --r;
                        v += seg[r];
                    }
                }
                ans[it.second] = v;
            }
            for (int c = 0; c < 26; c++) {
                int nxt = ch[cur][c];
                if (!nxt) continue;
                dfs_trie(nxt, ah_ch[state][c]);
            }
            for (int a = S+ah_st[state]; a; a /= 2) {
                seg[a] --;
            }
        })(0, 0);
    }

    for (int q = 0; q < M; q++) {
        cout << ans[q] << '\n';
    }

    return 0;
}


/*input
20
1 d
2 1 a
2 2 d
2 3 a
2 4 d
2 5 a
2 6 d
2 7 a
1 d
2 9 o
2 10 k
2 11 i
2 12 d
2 13 o
2 14 k
2 15 i
2 1 o
2 17 k
2 18 i
2 15 i
12
8 da
8 dada
8 ada
6 dada
3 dada
19 doki
19 ok
16 doki
15 doki
9 d
1 a
20 doki
*/
#include "bits/stdc++.h"
using namespace std;

template<typename T>
struct FenwickTree{
	vector<T> BIT;
	FenwickTree(int n){
		BIT = vector<T>(n+5);
	}
	void update(int idx, T val){
		for(++idx;idx < BIT.size(); idx += idx&-idx)
			BIT[idx] += val;
	}
	T query(int idx){
		T res(0);
		for(++idx;idx > 0; idx -= idx&-idx)
			res += BIT[idx];
		return res;
	}
	T query(int l, int r){
		return query(r) - query(l-1);
	}
};
FenwickTree<int> ST(400005);
struct node{
	map<char,node*> next;
	map<char,node*> jump;
	node *fail = NULL;
	vector<node*> adj;

	node *get(char c){
		if(jump.count(c))
			return jump[c];
		if(!fail || next.count(c))
			return this;

		return jump[c] = fail->get(c);
	}

	int tin, tout;
};

int CLK;
void euler(node *u){
	u->tin = ++CLK;
	for(auto i: u->adj)
		euler(i);
	u->tout = CLK;
}

vector<pair<int,int>> v[400005];
vector<pair<node*,int>> queries[400005];
int RES[400005];
void dfs(int u, node *cur){
	ST.update(cur->tin, 1);
	for(auto i:queries[u]){
		node *s = i.first;
		RES[i.second] = ST.query(s->tin, s->tout);
	}
	for(auto p: v[u]){
		int i = p.first; char c = p.second;
		node *nxt = cur->get(c);

		if(nxt->next.count(c))
			nxt = nxt->next[c];

		dfs(i, nxt);
	}
	ST.update(cur->tin, -1);
}

int main(){
	ios_base::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	int n, q; cin >> n;
	for(int i = 1; i <= n; ++i){
		int type; cin >> type;
		if(type == 1){
			char c; cin >> c;
			v[0].push_back({i, c});
		} else {
			int j; char c; cin >> j >> c;
			v[j].push_back({i, c});
		}
	}

	node *root = new node();

	cin >> q;
	for(int j = 0, i; j < q; ++j){
		string t; cin >> i >> t;
		node *cur = root;
		for(auto c: t){
			if(!cur->next.count(c))
				cur->next[c] = new node();
			cur = cur->next[c];
		}
		queries[i].push_back({cur, j});
	}

	queue<node*> bfs;
	for(auto i: root->next){
		root->adj.push_back(i.second);
		i.second->fail = root;
		bfs.push(i.second);
	}
	while(bfs.size()){
		auto u = bfs.front(); bfs.pop();
		for(auto p: u->next){
			char c = p.first; node *nxt = p.second;
			node *f = u->fail;

			while(f->fail && !f->next.count(c))
				f = f->fail;

			if(f->next.count(c))
				f = f->next[c];

			f->adj.push_back(nxt);
			nxt->fail = f;
			bfs.push(nxt);
		}
	}

	euler(root);
	dfs(0, root);

	for(int i = 0; i < q; ++i)
		cout << RES[i] << '\n';
}


/*input
20
1 d
2 1 a
2 2 d
2 3 a
2 4 d
2 5 a
2 6 d
2 7 a
1 d
2 9 o
2 10 k
2 11 i
2 12 d
2 13 o
2 14 k
2 15 i
2 1 o
2 17 k
2 18 i
2 15 i
12
8 da
8 dada
8 ada
6 dada
3 dada
19 doki
19 ok
16 doki
15 doki
9 d
1 a
20 doki
*/
#include "bits/stdc++.h"
using namespace std;

template<typename T>
struct FenwickTree{
	vector<T> BIT;
	FenwickTree(int n){
		BIT = vector<T>(n+5);
	}
	void update(int idx, T val){
		for(++idx;idx < BIT.size(); idx += idx&-idx)
			BIT[idx] += val;
	}
	T query(int idx){
		T res(0);
		for(++idx;idx > 0; idx -= idx&-idx)
			res += BIT[idx];
		return res;
	}
	T query(int l, int r){
		return query(r) - query(l-1);
	}
};
FenwickTree<int> ST(400005);
struct node{
	vector<int> is_leaf;
	map<char,node*> next;
	node *fail = NULL;
	vector<node*> adj;

	int tin;
	int tout;
};

int CLK;
void euler(node *u){
	u->tin = ++CLK;
	for(auto i: u->adj)
		euler(i);
	u->tout = CLK;
}

vector<pair<int,int>> v[400005];
vector<pair<node*,int>> queries[400005];
int RES[400005];
void dfs(int u, node *cur){
	ST.update(cur->tin, 1);
	for(auto i:queries[u]){
		node *s = i.first;
		RES[i.second] = ST.query(s->tin, s->tout);
	}
	for(auto p: v[u]){
		int i = p.first; char c = p.second;
		node *nxt = cur;
		while(nxt->fail && !nxt->next.count(c))
			nxt = nxt->fail;
		if(nxt->next.count(c))
			nxt = nxt->next[c];
		dfs(i, nxt);
	}
	ST.update(cur->tin, -1);
}

int main(){
	ios_base::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	int n, q; cin >> n;
	for(int i = 1; i <= n; ++i){
		int type; cin >> type;
		if(type == 1){
			char c; cin >> c;
			v[0].push_back({i, c});
		} else {
			int j; char c; cin >> j >> c;
			v[j].push_back({i, c});
		}
	}

	node *root = new node();

	cin >> q;
	for(int j = 0, i; j < q; ++j){
		string t; cin >> i >> t;
		node *cur = root;
		for(auto c: t){
			if(!cur->next.count(c))
				cur->next[c] = new node();
			cur = cur->next[c];
		}
		cur->is_leaf.push_back(j);
		queries[i].push_back({cur, j});
	}

	queue<node*> bfs;
	for(auto i: root->next){
		root->adj.push_back(i.second);
		i.second->fail = root;
		bfs.push(i.second);
	}
	while(bfs.size()){
		auto u = bfs.front(); bfs.pop();
		for(auto p: u->next){
			char c = p.first; node *nxt = p.second;
			node *f = u->fail;
			while(f->fail && !f->next.count(c))
				f = f->fail;
			if(f->next.count(c))
				f = f->next[c];

			f->adj.push_back(nxt);
			nxt->fail = f;
			bfs.push(nxt);
		}
	}

	euler(root);
	dfs(0, root);

	for(int i = 0; i < q; ++i)
		cout << RES[i] << '\n';
}


/*input
20
1 d
2 1 a
2 2 d
2 3 a
2 4 d
2 5 a
2 6 d
2 7 a
1 d
2 9 o
2 10 k
2 11 i
2 12 d
2 13 o
2 14 k
2 15 i
2 1 o
2 17 k
2 18 i
2 15 i
12
8 da
8 dada
8 ada
6 dada
3 dada
19 doki
19 ok
16 doki
15 doki
9 d
1 a
20 doki
*/
#include "bits/stdc++.h"
using namespace std;

template<typename T>
struct FenwickTree{
	vector<T> BIT;
	FenwickTree(int n){
		BIT = vector<T>(n+5);
	}
	void update(int idx, T val){
		for(++idx;idx < BIT.size(); idx += idx&-idx)
			BIT[idx] += val;
	}
	T query(int idx){
		T res(0);
		for(++idx;idx > 0; idx -= idx&-idx)
			res += BIT[idx];
		return res;
	}
	T query(int l, int r){
		return query(r) - query(l-1);
	}
};
FenwickTree<int> ST(400005);
struct node{
	map<char,node*> next;
	map<char,node*> jump;
	node *fail = NULL;
	vector<node*> adj;

	node *get(char c){
		if(jump.count(c))
			return jump[c];
		if(!fail || next.count(c))
			return this;

		return jump[c] = fail->get(c);
	}

	int tin, tout;
};

int CLK;
void euler(node *u){
	u->tin = ++CLK;
	for(auto i: u->adj)
		euler(i);
	u->tout = CLK;
}

vector<pair<int,int>> v[400005];
vector<pair<node*,int>> queries[400005];
int RES[400005];
void dfs(int u, node *cur){
	ST.update(cur->tin, 1);
	for(auto i:queries[u]){
		node *s = i.first;
		RES[i.second] = ST.query(s->tin, s->tout);
	}
	for(auto p: v[u]){
		int i = p.first; char c = p.second;
		node *nxt = cur->get(c);

		if(nxt->next.count(c))
			nxt = nxt->next[c];

		dfs(i, nxt);
	}
	ST.update(cur->tin, -1);
}

int main(){
	ios_base::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	int n, q; cin >> n;
	for(int i = 1; i <= n; ++i){
		int type; cin >> type;
		if(type == 1){
			char c; cin >> c;
			v[0].push_back({i, c});
		} else {
			int j; char c; cin >> j >> c;
			v[j].push_back({i, c});
		}
	}

	node *root = new node();

	cin >> q;
	for(int j = 0, i; j < q; ++j){
		string t; cin >> i >> t;
		node *cur = root;
		for(auto c: t){
			if(!cur->next.count(c))
				cur->next[c] = new node();
			cur = cur->next[c];
		}
		queries[i].push_back({cur, j});
	}

	queue<node*> bfs;
	for(auto i: root->next){
		root->adj.push_back(i.second);
		i.second->fail = root;
		bfs.push(i.second);
	}
	while(bfs.size()){
		auto u = bfs.front(); bfs.pop();
		for(auto p: u->next){
			char c = p.first; node *nxt = p.second;
			node *f = u->fail->get(c);

			if(f->next.count(c))
				f = f->next[c];

			f->adj.push_back(nxt);
			nxt->fail = f;
			bfs.push(nxt);
		}
	}

	euler(root);
	dfs(0, root);

	for(int i = 0; i < q; ++i)
		cout << RES[i] << '\n';
}


/*input
20
1 d
2 1 a
2 2 d
2 3 a
2 4 d
2 5 a
2 6 d
2 7 a
1 d
2 9 o
2 10 k
2 11 i
2 12 d
2 13 o
2 14 k
2 15 i
2 1 o
2 17 k
2 18 i
2 15 i
12
8 da
8 dada
8 ada
6 dada
3 dada
19 doki
19 ok
16 doki
15 doki
9 d
1 a
20 doki
*/
#include "bits/stdc++.h"
using namespace std;

template<typename T>
struct FenwickTree{
	vector<T> BIT;
	FenwickTree(int n){
		BIT = vector<T>(n+5);
	}
	void update(int idx, T val){
		for(++idx;idx < BIT.size(); idx += idx&-idx)
			BIT[idx] += val;
	}
	T query(int idx){
		T res(0);
		for(++idx;idx > 0; idx -= idx&-idx)
			res += BIT[idx];
		return res;
	}
	T query(int l, int r){
		return query(r) - query(l-1);
	}
};
FenwickTree<int> ST(400005);
struct node{
	map<char,node*> next;
	map<char,node*> jump;
	node *fail = NULL;
	vector<node*> adj;

	int tin, tout;
};

int CLK;
void euler(node *u){
	u->tin = ++CLK;
	for(auto i: u->adj)
		euler(i);
	u->tout = CLK;
}

vector<pair<int,int>> v[400005];
vector<pair<node*,int>> queries[400005];
int RES[400005];
void dfs(int u, node *cur){
	ST.update(cur->tin, 1);
	for(auto i:queries[u]){
		node *s = i.first;
		RES[i.second] = ST.query(s->tin, s->tout);
	}
	for(auto p: v[u]){
		int i = p.first; char c = p.second;
		node *nxt = cur;
		if(cur->jump.count(c)){
			nxt = cur->jump[c];
		} else{
			while(nxt->fail && !nxt->next.count(c))
				nxt = nxt->fail;
			if(nxt->next.count(c))
				nxt = nxt->next[c];

			cur->jump[c] = nxt;
		}
		dfs(i, nxt);
	}
	ST.update(cur->tin, -1);
}

int main(){
	ios_base::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	int n, q; cin >> n;
	for(int i = 1; i <= n; ++i){
		int type; cin >> type;
		if(type == 1){
			char c; cin >> c;
			v[0].push_back({i, c});
		} else {
			int j; char c; cin >> j >> c;
			v[j].push_back({i, c});
		}
	}

	node *root = new node();

	cin >> q;
	for(int j = 0, i; j < q; ++j){
		string t; cin >> i >> t;
		node *cur = root;
		for(auto c: t){
			if(!cur->next.count(c))
				cur->next[c] = new node();
			cur = cur->next[c];
		}
		queries[i].push_back({cur, j});
	}

	queue<node*> bfs;
	for(auto i: root->next){
		root->adj.push_back(i.second);
		i.second->fail = root;
		bfs.push(i.second);
	}
	while(bfs.size()){
		auto u = bfs.front(); bfs.pop();
		for(auto p: u->next){
			char c = p.first; node *nxt = p.second;
			node *f = u->fail;

			while(f->fail && !f->next.count(c))
				f = f->fail;

			if(f->next.count(c))
				f = f->next[c];

			f->adj.push_back(nxt);
			nxt->fail = f;
			bfs.push(nxt);
		}
	}

	euler(root);
	dfs(0, root);

	for(int i = 0; i < q; ++i)
		cout << RES[i] << '\n';
}


/*program by mangoyang*/
#include <bits/stdc++.h>
#define inf ((ll) 1e18)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
	int ch = 0, f = 0; x = 0;
	for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
	for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
	if(f) x = -x;
}

const int N = 1600005;

vector<int> g[N], d[N], rt;
vector<pair<int, int> > q[N];
string str[N];
char strr[N];
int ans[N], n, m;

namespace Bit{
    int s[N];
    inline void modify(int x, int y){
        for(int i = x; i < N; i += i & -i) s[i] += y;
    }
    inline int query(int l, int r){
        int res = 0;
        for(int i = l - 1; i; i -= i & -i) res -= s[i];
        for(int i = r; i; i -= i & -i) res += s[i];
        return res;
    }
}
namespace SAM{
    vector<int> g[N];
    int ch[N][27], dfn[N], len[N], fa[N], sz[N], size = 1, tail = 1, cnt;
    inline int newnode(int x){ return len[++size] = x, size; }
    inline void ins(int c, int pos){
        int p = tail;
        if(ch[p][c]){
            if(ch[p][c] && len[ch[p][c]] == len[p] + 1){
                int np = ch[p][c];
                if(pos <= n) d[pos].push_back(np);
                return (void) (tail = np);
            }
            int np = newnode(len[p] + 1), q = ch[p][c];
            if(pos <= n) d[pos].push_back(np);
            fa[np] = fa[q], fa[q] = np;
            for(int i = 0; i < 26; i++) ch[np][i] = ch[q][i];
            for(; p && ch[p][c] == q; p = fa[p]) ch[p][c] = np;
            return (void) (tail = np);
        }
        int np = newnode(len[p] + 1);
        if(pos <= n) d[pos].push_back(np);
        for(; p && !ch[p][c]; p = fa[p]) ch[p][c] = np;
        if(!p) return (void) (fa[np] = 1, tail = np);
        int q = ch[p][c];
        if(len[q] == len[p] + 1) fa[np] = q;
        else{
            int nq = newnode(len[p] + 1);
            fa[nq] = fa[q], fa[q] = fa[np] = nq;
            for(int i = 0; i < 26; i++) ch[nq][i] = ch[q][i];
            for(; p && ch[p][c] == q; p = fa[p]) ch[p][c] = nq;
        } tail = np;
    }
    inline void addedge(){
        for(int i = 2; i <= size; i++) g[fa[i]].push_back(i);
    }
    inline void dfs(int u){
        dfn[u] = ++cnt, sz[u] = 1;
        for(int i = 0; i < (int) g[u].size(); i++)
            dfs(g[u][i]), sz[u] += sz[g[u][i]];
    }
}
inline void build(int u){
    int tmp = SAM::tail;
    for(int i = 0; i < (int) str[u].size(); i++)
        SAM::ins(str[u][i] - 'a', u);
    for(int i = 0; i < (int) g[u].size(); i++)
        build(g[u][i]);
    SAM::tail = tmp;
}
inline void solve(int u){
    for(int i = 0; i < (int) d[u].size(); i++)
        Bit::modify(SAM::dfn[d[u][i]], 1);
    for(int i = 0; i < (int) q[u].size(); i++){
        int x = q[u][i].first, y = q[u][i].second;
        ans[x] = Bit::query(SAM::dfn[y], SAM::dfn[y] + SAM::sz[y] - 1);
    }
    for(int i = 0; i < (int) g[u].size(); i++)
        solve(g[u][i]);
    for(int i = 0; i < (int) d[u].size(); i++)
        Bit::modify(SAM::dfn[d[u][i]], -1);
}
int main(){
    read(n);
    for(int i = 1, x, y; i <= n; i++){
        read(x);
        if(x == 1)
            cin >> str[i], rt.push_back(i);
        else
            read(y), cin >> str[i], g[y].push_back(i);
    }
    for(int i = 0; i < (int) rt.size(); i++)
        build(rt[i]);
    read(m);
    for(int i = 1, x; i <= m; i++){
        read(x), scanf("%s", strr);
        int lenth = strlen(strr);
        for(int j = 0; j < lenth; j++)
            SAM::ins(strr[j] - 'a', n + 1);
        q[x].push_back(make_pair(i, SAM::tail));
        SAM::tail = 1;
    }
    SAM::addedge(), SAM::dfs(1);
    for(int i = 0; i < (int) rt.size(); i++)
        solve(rt[i]);
    for(int i = 1; i <= m; i++) printf("%d\n", ans[i]);
    return 0;


/*program by mangoyang*/
#include <bits/stdc++.h>
#define inf ((ll) 1e18)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
	int ch = 0, f = 0; x = 0;
	for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
	for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
	if(f) x = -x;
}

const int N = 1600005;

vector<int> g[N], d[N], rt;
vector<pair<int, int> > q[N];
string str[N];
char strr[N];
int ans[N], n, m;

namespace Bit{
    int s[N];
    inline void modify(int x, int y){
        for(int i = x; i < N; i += i & -i) s[i] += y;
    }
    inline int query(int l, int r){
        int res = 0;
        for(int i = l - 1; i; i -= i & -i) res -= s[i];
        for(int i = r; i; i -= i & -i) res += s[i];
        return res;
    }
}
namespace SAM{
    vector<int> g[N];
    int ch[N][27], dfn[N], len[N], fa[N], sz[N], size = 1, tail = 1, cnt;
    inline int newnode(int x){ return len[++size] = x, size; }
    inline void ins(int c, int pos){
        int p = tail;
        if(ch[p][c]){
            if(ch[p][c] && len[ch[p][c]] == len[p] + 1){
                int np = ch[p][c];
                if(pos <= n) d[pos].push_back(np);
                return (void) (tail = np);
            }
            int np = newnode(len[p] + 1), q = ch[p][c];
            if(pos <= n) d[pos].push_back(np);
            fa[np] = fa[q], fa[q] = np;
            for(int i = 0; i < 26; i++) ch[np][i] = ch[q][i];
            for(; p && ch[p][c] == q; p = fa[p]) ch[p][c] = np;
            return (void) (tail = np);
        }
        int np = newnode(len[p] + 1);
        if(pos <= n) d[pos].push_back(np);
        for(; p && !ch[p][c]; p = fa[p]) ch[p][c] = np;
        if(!p) return (void) (fa[np] = 1, tail = np);
        int q = ch[p][c];
        if(len[q] == len[p] + 1) fa[np] = q;
        else{
            int nq = newnode(len[p] + 1);
            fa[nq] = fa[q], fa[q] = fa[np] = nq;
            for(int i = 0; i < 26; i++) ch[nq][i] = ch[q][i];
            for(; p && ch[p][c] == q; p = fa[p]) ch[p][c] = nq;
        } tail = np;
    }
    inline void addedge(){
        for(int i = 2; i <= size; i++) g[fa[i]].push_back(i);
    }
    inline void dfs(int u){
        dfn[u] = ++cnt, sz[u] = 1;
        for(int i = 0; i < (int) g[u].size(); i++)
            dfs(g[u][i]), sz[u] += sz[g[u][i]];
    }
}
inline void build(int u){
    int tmp = SAM::tail;
    for(int i = 0; i < (int) str[u].size(); i++)
        SAM::ins(str[u][i] - 'a', u);
    for(int i = 0; i < (int) g[u].size(); i++)
        build(g[u][i]);
    SAM::tail = tmp;
}
inline void solve(int u){
    for(int i = 0; i < (int) d[u].size(); i++)
        Bit::modify(SAM::dfn[d[u][i]], 1);
    for(int i = 0; i < (int) q[u].size(); i++){
        int x = q[u][i].first, y = q[u][i].second;
        ans[x] = Bit::query(SAM::dfn[y], SAM::dfn[y] + SAM::sz[y] - 1);
    }
    for(int i = 0; i < (int) g[u].size(); i++)
        solve(g[u][i]);
    for(int i = 0; i < (int) d[u].size(); i++)
        Bit::modify(SAM::dfn[d[u][i]], -1);
}
int main(){
    read(n);
    for(int i = 1, x, y; i <= n; i++){
        read(x);
        if(x == 1)
            cin >> str[i], rt.push_back(i);
        else
            read(y), cin >> str[i], g[y].push_back(i);
    }
    for(int i = 0; i < (int) rt.size(); i++)
        build(rt[i]);
    read(m);
    for(int i = 1, x; i <= m; i++){
        read(x), scanf("%s", strr);
        int lenth = strlen(strr);
        for(int j = 0; j < lenth; j++)
            SAM::ins(strr[j] - 'a', n + 1);
        q[x].push_back(make_pair(i, SAM::tail));
        SAM::tail = 1;
    }
    SAM::addedge(), SAM::dfs(1);
    for(int i = 0; i < (int) rt.size(); i++)
        solve(rt[i]);
    for(int i = 1; i <= m; i++) printf("%d\n", ans[i]);
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

template <class T,class U>
void maximize(T &x,U y){
    if(x < y)x = y;
}
template <class T,class U>
void minimize(T &x,U y){
    if(x > y)x = y;
}
template <class T>
T Abs(T x){
    return (x < (T)0 ? -x : x);
}

#define len(c) (int)((c).size())
#define llong long long
#define MASK(i) ((1LL) << (i))
#define BIT(x,i) (((x) >> (i)) & 1)
#define all(c) (c).begin(),(c).end()
#define fn "test"    ///FILE_NAME_HERE

/*----------END_OF_TEMPLATE----------*/

namespace task{

    const int N = 1e5 + 5;
    vector <int> adj[N];
    vector <int> ans;
    int d[N],a[N],ord[N];
    int n,m;

    void solve(){
        cin>>n>>m;
        for(int i = 1;i <= m;++i){
            int u,v;
            cin>>u>>v;
            adj[u].emplace_back(v);
            adj[v].emplace_back(u);
        }
        for(int i = 1;i <= n;++i){
            cin>>a[i];
            ord[i] = i;
            d[i] = -a[i];
        }
        sort(ord + 1,ord + 1 + n,[&](const int &u,const int &v) -> bool{
            return d[u] < d[v];
        });
        set < pair <int,int> > heap;
        for(int u = 1;u <= n;++u){
            if(!d[u]) {
                heap.insert(make_pair(d[u], u));
            }
        }
        while(!heap.empty()){
            while(!heap.empty() and heap.begin() -> first != 0){
                heap.erase(heap.begin());
            }
            if(!heap.empty()){
                pair <int,int> top = *heap.begin();
                heap.erase(heap.begin());
                int u = top.second;
                ans.emplace_back(u);
                for(int v : adj[u]){
                    if(heap.find(make_pair(d[v],v)) != heap.end()){
                        heap.erase(heap.find(make_pair(d[v],v)));
                    }
                    ++d[v];
                    if(d[v] == 0){
                        heap.insert(make_pair(d[v],v));
                    }
                }
            }
        }
        auto cnt = [&]() -> int{
            int cc = 0;
            for(int u = 1;u <= n;++u){
                cc += d[u] == 0;
            }
            return cc == n;
        };
        if(cnt()){
            cout<<-1;
            exit(0);
        }
        cout<<len(ans)<<'\n';
        for(int val : ans){
            cout<<val<<' ';
        }
    }
}

int main(void){
    ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    #ifndef ONLINE_JUDGE
    freopen(fn".inp","r",stdin);
    //freopen(fn".out","w",stdout);
    #endif // ONLINE_JUDGE
    task::solve();
}


#include <bits/stdc++.h>
using namespace std;
int counters[100005],expected[100005],clicked[100005],visited[100005];
vector<int> wires[100005];
vector<int> clicks;
void bfs(int i)
{
    visited[i] = 1;
    queue<int> bfss;
    bfss.push(i);
    while(!bfss.empty())
    {
        int i = bfss.front();
        bfss.pop();
        visited[i] = 1;
        for(vector<int>::iterator itr = wires[i].begin(); itr != wires[i].end();itr++)
            if(!visited[*itr])
                bfss.push(*itr);
        if(expected[i] >= counters[i])
        {
            counters[i]++;
            clicks.push_back(i);
            for(vector<int>::iterator itr = wires[i].begin(); itr != wires[i].end();itr++)
                counters[*itr]++;
        }
    }

}
int main()
{
    //freopen("input.txt","r",stdin); freopen("output.txt","w",stdout);
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    int n,m;
    cin >> n >> m;
    for(int i = 0;i < m;i++)
    {
        int x,y;
        cin >> x >> y;
        wires[x-1].push_back(y-1);
        wires[y-1].push_back(x-1);
    }
    for(int i = 0;i < n;i++)
        cin >> expected[i];
    for(int i = 0;i < n;i++)
        if(!visited[i])
            bfs(i);
    for(int i = 0;i < n;i++)
    {
        if(expected[i] == counters[i])
        {
            cout << -1;
            return 0;
        }
    }
    sort(clicks.begin(),clicks.end());
    cout << clicks.size() << endl;
    for(int i = 0;i < clicks.size();i++)
        cout << clicks[i] << " ";
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
int counters[100005],expected[100005],clicked[100005],visited[100005];
vector<int> wires[100005];
void bfs(int i)
{
    visited[i] = 1;
    queue<int> bfss;
    bfss.push(i);
    while(!bfss.empty())
    {
        int i = bfss.front();
        bfss.pop();
        visited[i] = 1;
        for(vector<int>::iterator itr = wires[i].begin(); itr != wires[i].end();itr++)
            if(!visited[*itr])
                bfss.push(*itr);
        if(expected[i] >= counters[i])
        {
            counters[i]++;
            for(vector<int>::iterator itr = wires[i].begin(); itr != wires[i].end();itr++)
                counters[*itr]++;
        }
    }

}
int main()
{
    //freopen("input.txt","r",stdin); freopen("output.txt","w",stdout);
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    int n,m;
    cin >> n >> m;
    for(int i = 0;i < m;i++)
    {
        int x,y;
        cin >> x >> y;
        wires[x-1].push_back(y-1);
        wires[y-1].push_back(x-1);
    }
    for(int i = 0;i < n;i++)
        cin >> expected[i];
    for(int i = 0;i < n;i++)
        if(!visited[i])
            bfs(i);
    for(int i = 0;i < n;i++)
    {
        if(expected[i] == counters[i])
        {
            cout << -1;
            return 0;
        }
    }
    for(int i = 0;i < n;i++)
        cout << counters[i] << " ";
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
int counters[100005],expected[100005],clicked[100005],visited[100005];
vector<int> wires[100005];
vector<int> clicks;
void bfs(int i)
{
    visited[i] = 1;
    queue<int> bfss;
    bfss.push(i);
    while(!bfss.empty())
    {
        int i = bfss.front();
        bfss.pop();
        visited[i] = 1;
        for(vector<int>::iterator itr = wires[i].begin(); itr != wires[i].end();itr++)
            if(!visited[*itr])
                bfss.push(*itr);
        if(expected[i] == counters[i])
        {
            counters[i]++;
            clicks.push_back(i);
            for(vector<int>::iterator itr = wires[i].begin(); itr != wires[i].end();itr++)
            {
                counters[*itr]++;
                bfss.push(*itr);
            }
        }
    }

}
int main()
{
    //freopen("input.txt","r",stdin); freopen("output.txt","w",stdout);
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    int n,m;
    cin >> n >> m;
    for(int i = 0;i < m;i++)
    {
        int x,y;
        cin >> x >> y;
        wires[x-1].push_back(y-1);
        wires[y-1].push_back(x-1);
    }
    for(int i = 0;i < n;i++)
        cin >> expected[i];
    for(int i = 0;i < n;i++)
        if(!visited[i])
            bfs(i);
    for(int i = 0;i < n;i++)
    {
        if(expected[i] == counters[i])
        {
            cout << -1;
            return 0;
        }
    }
    sort(clicks.begin(),clicks.end());
    cout << clicks.size() << endl;
    for(int i = 0;i < clicks.size();i++)
        cout << clicks[i] + 1 << " ";
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
int counters[100005],expected[100005],clicked[100005],visited[100005];
vector<int> wires[100005];
vector<int> clicks;
void bfs(int i)
{
    visited[i] = 1;
    queue<int> bfss;
    bfss.push(i);
    while(!bfss.empty())
    {
        int i = bfss.front();
        bfss.pop();
        visited[i] = 1;
        for(vector<int>::iterator itr = wires[i].begin(); itr != wires[i].end();itr++)
            if(!visited[*itr])
                bfss.push(*itr);
        if(expected[i] >= counters[i])
        {
            counters[i]++;
            clicks.push_back(i);
            for(vector<int>::iterator itr = wires[i].begin(); itr != wires[i].end();itr++)
                counters[*itr]++;
        }
    }

}
int main()
{
    //freopen("input.txt","r",stdin); freopen("output.txt","w",stdout);
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    int n,m;
    cin >> n >> m;
    for(int i = 0;i < m;i++)
    {
        int x,y;
        cin >> x >> y;
        wires[x-1].push_back(y-1);
        wires[y-1].push_back(x-1);
    }
    for(int i = 0;i < n;i++)
        cin >> expected[i];
    for(int i = 0;i < n;i++)
        if(!visited[i])
            bfs(i);
    for(int i = 0;i < n;i++)
    {
        if(expected[i] == counters[i])
        {
            cout << -1;
            return 0;
        }
    }
    sort(clicks.begin(),clicks.end());
    cout << clicks.size() << endl;
    for(int i = 0;i < clicks.size();i++)
        cout << clicks[i] + 1 << " ";
    return 0;
}