#include<bits/stdc++.h>
using namespace std;
struct lsg{int x,y;}a[100000];
int n,t,ans,kk,z[100],zz[100];
int doit(int x,int y){return(a[x].x-a[y].x)*(a[x].x-a[y].x)+(a[x].y-a[y].y)*(a[x].y-a[y].y);}
int dfs(int d,int dd,int sum){
if(d==n+1){ans=sum;for(int i=1;i<=n;i++)zz[i]=z[i];return 0;}
for(int i=dd;i<=kk;i++){
int sum1=sum;for(int j=1;j<d;j++)sum1+=doit(z[j],i);
z[d]=i;if(sum1+(n*n-d*d)*4*t*t>ans)dfs(d+1,i,sum1);
}
}
bool pd(lsg x,lsg y){return x.x*x.x+x.y*x.y>y.y*y.y+y.x*y.x;}
int main(){
ios::sync_with_stdio(false);
cin>>n>>t;for(int i=-t;i<=t;i++)
for(int j=-t;j<=t;j++)if(i*i+j*j<=t*t)a[++kk].x=i,a[kk].y=j;
sort(a+1,a+1+kk,pd);kk=min(kk,20);
dfs(1,1,0);cout<<ans<<endl;
for(int i=1;i<=n;i++)cout<<a[zz[i]].x<<' '<<a[zz[i]].y<<endl;
}


#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
#define x first
#define y second
#define mp make_pair
int n,r,k,ans,p[15];
pii a[4010],b[15];
int dis(pii x,pii y)
{
	return (x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y);
}
bool cmp(pii x,pii y)
{
	return dis(x,a[0])>dis(y,a[0]);
}
void dfs(int x,int y,int s)
{
	if (x==n+1)
	{
		if (s>ans)
		{
			ans=s;
			for (int i=1;i<=n;i++)
			{
				b[i]=a[p[i]];
			}
		}
		return;
	}
	for (int i=y;i<=k;i++)
	{
		int tmp=0;
		for (int j=1;j<x;j++)
		{
			tmp+=dis(a[p[j]],a[i]);
		}
		p[x]=i;
		if (s+tmp+(n*n-x*x)*4*r*r>ans)
		{
			dfs(x+1,i,s+tmp);
		}
	}
}
int main()
{
	cin>>n>>r;
	for (int i=-r;i<=r;i++)
	{
		for (int j=-r;j<=r;j++)
		{
			if (i*i+j*j<=r*r)
			{
				a[++k]=mp(i,j);
			}
		}
	}
	sort(a+1,a+k+1,cmp);
	k=min(k,18);
	dfs(1,1,0);
	cout<<ans<<endl;
	for (int i=1;i<=n;i++)
	{
		cout<<b[i].x<<" "<<b[i].y<<endl;
	}
	return 0;
}
//雨中草色绿堪染,水上桃花红欲燃。
//——王维《辋川别业》


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

#define rep(i,a,b) for (int i=a;i<=b;i++)
#define REP(i,a,b) for (int i=a;i>=b;i--)

// int n,r,ans[9][31];
int n,r,ans=0;

struct Point
{
    int x,y;
    Point () {}
    inline Point(int xx,int yy) {x=xx;y=yy;}
    inline bool inner() {return x*x+y*y<=r*r;}
}a[1048],c[48],aa[48];int tot=0;

inline int area(Point A,Point B,Point C)
{
    int x1=B.x-A.x,y1=B.y-A.y,x2=C.x-A.x,y2=C.y-A.y;
    return y1*x2-x1*y2;
}

inline void gen()
{
    tot=0;a[++tot]=Point(0,r);
    for (;;)
    {
        Point cur=a[tot];
        cur.x++;while (!cur.inner()) cur.y--;
        while (cur.inner()) cur.x++;cur.x--;
        if (cur.y==0) break;
        if (area(a[tot],cur,Point(r,0))>=0) a[++tot]=cur;
        while (tot>=3 && area(a[tot-2],a[tot-1],a[tot])<=0) a[tot-1]=a[tot],tot--;
    }
    int t=tot;
    rep(i,1,t) a[++tot].x=-a[i].y,a[tot].y=a[i].x;
    rep(i,1,t) a[++tot].x=-a[i].x,a[tot].y=-a[i].y;
    rep(i,1,t) a[++tot].x=a[i].y,a[tot].y=-a[i].x;
}

inline int calc()
{
    int res=0;
    rep(i,1,n-1) rep(j,i+1,n) res+=(c[i].x-c[j].x)*(c[i].x-c[j].x)+(c[i].y-c[j].y)*(c[i].y-c[j].y);
    return res;
}

inline void dfs(int cur,int chosen)
{
    if (chosen==n)
    {
        int cc=calc();
        if (cc>ans)
        {
            ans=cc;
            rep(i,1,n) aa[i]=c[i];
        }
        return;
    }
    // if (chosen==n) {ans[n][r]=max(ans[n][r],calc());return;
    if (cur>tot) return;
    rep(i,cur,tot) c[chosen+1]=a[i],dfs(i,chosen+1);
}

int main ()
{
#ifndef ONLINE_JUDGE
    double T=clock();
    freopen ("a.in","r",stdin);
    freopen ("a.out","w",stdout);
    cerr<<"Running..."<<endl;
#endif
    /*
    int ca;scanf("%d",&ca);
    rep(i,1,8) rep(j,1,30) ans[i][j]=-1;
    while (ca--)
    {
        scanf("%d%d",&n,&r);
        if (n%2==0) {printf("%d\n",n*n*r*r);continue;}
        if (ans[n][r]!=-1) {printf("%d\n",ans[n][r]);continue;}
        gen();cerr<<tot<<endl;dfs(1,0);printf("%d\n",ans[n][r]);
    }
    */
    scanf("%d%d",&n,&r);
    if (n%2==0)
    {
        printf("%d\n",n*n*r*r);
        rep(i,1,n/2) printf("%d 0\n",r);
        rep(i,1,n/2) printf("%d 0\n",-r);
        return 0;
    }
    gen();dfs(1,0);
    printf("%d\n",ans);
    rep(i,1,n) printf("%d %d\n",aa[i].x,aa[i].y);
#ifndef ONLINE_JUDGE
    cerr<<"Exec Time: "<<(clock()-T)/CLOCKS_PER_SEC<<endl;
#endif
    return 0;
}


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

#define rep(i,a,b) for (int i=a;i<=b;i++)
#define REP(i,a,b) for (int i=a;i>=b;i--)

// int n,r,ans[9][31];
int n,r,ans=0;

struct Point
{
    int x,y;
    Point () {}
    inline Point(int xx,int yy) {x=xx;y=yy;}
    inline bool inner() {return x*x+y*y<=r*r;}
}a[1048],c[48],aa[48];int tot=0;

inline int area(Point A,Point B,Point C)
{
    int x1=B.x-A.x,y1=B.y-A.y,x2=C.x-A.x,y2=C.y-A.y;
    return y1*x2-x1*y2;
}

inline void gen()
{
    tot=0;a[++tot]=Point(0,r);
    for (;;)
    {
        Point cur=a[tot];
        cur.x++;while (!cur.inner()) cur.y--;
        while (cur.inner()) cur.x++;cur.x--;
        if (cur.y==0) break;
        if (area(a[tot],cur,Point(r,0))>=0) a[++tot]=cur;
        while (tot>=3 && area(a[tot-2],a[tot-1],a[tot])<=0) a[tot-1]=a[tot],tot--;
    }
    int t=tot;
    rep(i,1,t) a[++tot].x=-a[i].y,a[tot].y=a[i].x;
    rep(i,1,t) a[++tot].x=-a[i].x,a[tot].y=-a[i].y;
    rep(i,1,t) a[++tot].x=a[i].y,a[tot].y=-a[i].x;
}

inline int calc()
{
    int res=0;
    rep(i,1,n-1) rep(j,i+1,n) res+=(c[i].x-c[j].x)*(c[i].x-c[j].x)+(c[i].y-c[j].y)*(c[i].y-c[j].y);
    return res;
}

inline void dfs(int cur,int chosen)
{
    if (chosen==n)
    {
        int cc=calc();
        if (cc>ans)
        {
            ans=cc;
            rep(i,1,n) aa[i]=c[i];
        }
        return;
    }
    // if (chosen==n) {ans[n][r]=max(ans[n][r],calc());return;
    if (cur>tot) return;
    rep(i,cur,tot) c[chosen+1]=a[i],dfs(i,chosen+1);
}

int main ()
{
#ifndef ONLINE_JUDGE
    double T=clock();
    freopen ("a.in","r",stdin);
    freopen ("a.out","w",stdout);
    cerr<<"Running..."<<endl;
#endif
    /*
    int ca;scanf("%d",&ca);
    rep(i,1,8) rep(j,1,30) ans[i][j]=-1;
    while (ca--)
    {
        scanf("%d%d",&n,&r);
        if (n%2==0) {printf("%d\n",n*n*r*r);continue;}
        if (ans[n][r]!=-1) {printf("%d\n",ans[n][r]);continue;}
        gen();cerr<<tot<<endl;dfs(1,0);printf("%d\n",ans[n][r]);
    }
    */
    scanf("%d%d",&n,&r);
    gen();dfs(1,0);
    printf("%d\n",ans);
    rep(i,1,n) printf("%d %d\n",aa[i].x,aa[i].y);
#ifndef ONLINE_JUDGE
    cerr<<"Exec Time: "<<(clock()-T)/CLOCKS_PER_SEC<<endl;
#endif
    return 0;
}


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

#define rep(i,a,b) for (int i=a;i<=b;i++)
#define REP(i,a,b) for (int i=a;i>=b;i--)

// int n,r,ans[9][31];
int n,r,ans=0;

struct Point
{
    int x,y;
    Point () {}
    inline Point(int xx,int yy) {x=xx;y=yy;}
    inline bool inner() {return x*x+y*y<=r*r;}
}a[1048],c[48],aa[48];int tot=0;

inline int area(Point A,Point B,Point C)
{
    int x1=B.x-A.x,y1=B.y-A.y,x2=C.x-A.x,y2=C.y-A.y;
    return y1*x2-x1*y2;
}

inline void gen()
{
    tot=0;a[++tot]=Point(0,r);
    for (;;)
    {
        Point cur=a[tot];
        cur.x++;while (!cur.inner()) cur.y--;
        while (cur.inner()) cur.x++;cur.x--;
        if (cur.y==0) break;
        if (area(a[tot],cur,Point(r,0))>=0) a[++tot]=cur;
        while (tot>=3 && area(a[tot-2],a[tot-1],a[tot])<=0) a[tot-1]=a[tot],tot--;
    }
    int t=tot;
    rep(i,1,t) a[++tot].x=-a[i].y,a[tot].y=a[i].x;
    rep(i,1,t) a[++tot].x=-a[i].x,a[tot].y=-a[i].y;
    rep(i,1,t) a[++tot].x=a[i].y,a[tot].y=-a[i].x;
    t=tot;while (tot<n) rep(i,1,t) a[++tot]=a[i];
}

inline int calc()
{
    int res=0;
    rep(i,1,n-1) rep(j,i+1,n) res+=(c[i].x-c[j].x)*(c[i].x-c[j].x)+(c[i].y-c[j].y)*(c[i].y-c[j].y);
    return res;
}

inline void dfs(int cur,int chosen)
{
    if (chosen==n)
    {
        int cc=calc();
        if (cc>ans)
        {
            ans=cc;
            rep(i,1,n) aa[i]=c[i];
        }
        return;
    }
    // if (chosen==n) {ans[n][r]=max(ans[n][r],calc());return;}
    if (cur>tot) return;
    dfs(cur+1,chosen);
    c[++chosen]=a[cur];dfs(cur+1,chosen);
}

int main ()
{
#ifndef ONLINE_JUDGE
    double T=clock();
    freopen ("a.in","r",stdin);
    freopen ("a.out","w",stdout);
    cerr<<"Running..."<<endl;
#endif
    /*
    int ca;scanf("%d",&ca);
    rep(i,1,8) rep(j,1,30) ans[i][j]=-1;
    while (ca--)
    {
        scanf("%d%d",&n,&r);
        if (n%2==0) {printf("%d\n",n*n*r*r);continue;}
        if (ans[n][r]!=-1) {printf("%d\n",ans[n][r]);continue;}
        gen();cerr<<tot<<endl;dfs(1,0);printf("%d\n",ans[n][r]);
    }
    */
    scanf("%d%d",&n,&r);
    gen();dfs(1,0);
    printf("%d\n",ans);
    rep(i,1,n) printf("%d %d\n",aa[i].x,aa[i].y);
#ifndef ONLINE_JUDGE
    cerr<<"Exec Time: "<<(clock()-T)/CLOCKS_PER_SEC<<endl;
#endif
    return 0;
}


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

#define rep(i,a,b) for (int i=a;i<=b;i++)
#define REP(i,a,b) for (int i=a;i>=b;i--)

// int n,r,ans[9][31];
int n,r,ans=0;

struct Point
{
    int x,y;
    Point () {}
    inline Point(int xx,int yy) {x=xx;y=yy;}
    inline bool inner() {return x*x+y*y<=r*r;}
}a[1048],c[48],aa[48];int tot=0;

inline int area(Point A,Point B,Point C)
{
    int x1=B.x-A.x,y1=B.y-A.y,x2=C.x-A.x,y2=C.y-A.y;
    return y1*x2-x1*y2;
}

inline void gen()
{
    tot=0;a[++tot]=Point(0,r);
    for (;;)
    {
        Point cur=a[tot];
        cur.x++;while (!cur.inner()) cur.y--;
        while (cur.inner()) cur.x++;cur.x--;
        if (cur.y==0) break;
        if (area(a[tot],cur,Point(r,0))>=0) a[++tot]=cur;
        while (tot>=3 && area(a[tot-2],a[tot-1],a[tot])<=0) a[tot-1]=a[tot],tot--;
    }
    int t=tot;
    rep(i,1,t) a[++tot]=a[i],a[tot].x=-a[tot].x;
    rep(i,1,t) a[++tot]=a[i],a[tot].y=-a[tot].y;
    rep(i,1,t) a[++tot]=a[i],a[tot].x=-a[tot].x,a[tot].y=-a[tot].y;
}

inline int calc()
{
    int res=0;
    rep(i,1,n-1) rep(j,i+1,n) res+=(c[i].x-c[j].x)*(c[i].x-c[j].x)+(c[i].y-c[j].y)*(c[i].y-c[j].y);
    return res;
}

inline void dfs(int cur,int chosen)
{
    if (chosen==n)
    {
        int cc=calc();
        if (cc>ans)
        {
            ans=cc;
            rep(i,1,n) aa[i]=c[i];
        }
        return;
    }
    // if (chosen==n) {ans[n][r]=max(ans[n][r],calc());return;}
    if (cur>tot) return;
    dfs(cur+1,chosen);
    c[++chosen]=a[cur];dfs(cur+1,chosen);
}

int main ()
{
#ifndef ONLINE_JUDGE
    double T=clock();
    freopen ("a.in","r",stdin);
    freopen ("a.out","w",stdout);
    cerr<<"Running..."<<endl;
#endif
    /*
    int ca;scanf("%d",&ca);
    rep(i,1,8) rep(j,1,30) ans[i][j]=-1;
    while (ca--)
    {
        scanf("%d%d",&n,&r);
        if (n%2==0) {printf("%d\n",n*n*r*r);continue;}
        if (ans[n][r]!=-1) {printf("%d\n",ans[n][r]);continue;}
        gen();cerr<<tot<<endl;dfs(1,0);printf("%d\n",ans[n][r]);
    }
    */
    scanf("%d%d",&n,&r);
    gen();dfs(1,0);
    printf("%d\n",ans);
    rep(i,1,n) printf("%d %d\n",aa[i].x,aa[i].y);
#ifndef ONLINE_JUDGE
    cerr<<"Exec Time: "<<(clock()-T)/CLOCKS_PER_SEC<<endl;
#endif
    return 0;
}


#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>

using namespace std;

struct point {
    int x, y;
    point (int x = 0, int y = 0) {
        this->x = x;
        this->y = y;
    }
};

int N, R, M, ans, pos[10], rec[10];
vector<point> vec;

inline int dis (int x, int y) {
    return x * x + y * y;
}

inline bool cmp (const point& a, const point& b) {
    return dis(a.x, a.y) > dis(b.x, b.y);
}

void init () {
    scanf("%d%d", &N, &R);
    for (int i = -R; i <= R; i++) {
        for (int j = -R; j <= R; j++)  {
            if (i * i + j * j <= R * R)
                vec.push_back(point(i, j));
        }
    }

    ans = 0;
    M = min((int)vec.size(), 18);
    sort(vec.begin(), vec.end(), cmp);
}

void dfs (int d, int f, int s) {
    if (d == N) {
        if (s > ans) {
            ans = s;
            memcpy(rec, pos, sizeof(pos));
        }
        return;
    }

    for (int i = f; i < M; i++) {
        int add = 0;
        for (int j = 0; j < d; j++)
            add += dis(vec[pos[j]].x - vec[i].x, vec[pos[j]].y - vec[i].y);
        pos[d] = i;
        dfs(d + 1, i, s + add);
    }
}

int main () {
    init();
    dfs(0, 0, 0);
    printf("%d\n", ans);
    for (int i = 0; i < N; i++)
        printf("%d %d\n", vec[rec[i]].x, vec[rec[i]].y);
    return 0;
}


// luogu-judger-enable-o2
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>

#define MAXN 10000

using namespace std;

struct Point
{
    int x,y;
    Point(){}
    Point(int _x,int _y):x(_x),y(_y){}
}points[MAXN],o;

int tot=0,n,r,m; //m=候选的点

inline int dist(Point a,Point b)
{
    return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}

bool cmp(Point a,Point b)
{
    return dist(a,o)>dist(b,o);
}

void init()
{
    scanf("%d%d",&n,&r);
    for(int i=-r;i<=r;i++)
        for(int j=-r;j<=r;j++)
            if(dist(Point(i,j),o)<=r*r)
                points[++tot]=Point(i,j);
    sort(points+1,points+tot+1,cmp);
    m=min(18,max(n,tot)); //!!!!取前18个距离圆心最远的点,若找到的在半径为r的圆内的点个数不到n，剩下的点用(0,0)补齐！
}

int ans[MAXN],maxans;

int numofpoint[MAXN],stack[MAXN],top=0;

void DFS(int x,int used,int sum) //搜到第x个可行点，已经选了used个点，当前的两两距离平方和为sum
{
    if(used==n)
    {
        if(maxans<sum)
        {
            maxans=sum;
            memcpy(ans,stack,sizeof(stack));
        }
        return;
    }
    for(int i=x;i<=m;i++)
    {
        stack[++top]=i;
        int tmp=0;
        for(int j=1;j<top;j++)
            tmp+=dist(points[stack[j]],points[i]);
        DFS(i,used+1,sum+tmp); //!!!!!
        top--;
    }
}

int main()
{
    init();
    DFS(1,0,0);
    printf("%d\n",maxans);
    for(int i=1;i<=n;i++)
        printf("%d %d\n",points[ans[i]].x,points[ans[i]].y);
    return 0;
}
//hellobig_tq


#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define rint register int
#define infl 0x3f3f3f3f3f3f3f3fll
#define rep(i,a,n) for(rint i=(a);i<=(n);i++)
#define repv(i,n,a) for(rint i=(n);i>=(a);i--)
#define lowbit(x) ((x)&-(x))
#define mset(x,v) memset(x,(v),sizeof(x))
#define mkp make_pair
#define pii pair<int,int>
#define pll pair<ll,ll>
#define x1 first
#define x2 second
#define ll long long
#define maxn 200005
using namespace std;
inline ll read(){
    ll s=0,f=1; char c=getchar();
    while(c<'0'||c>'9') f*=c=='-'?-1:1,c=getchar();
    while(c>='0'&&c<='9') s=s*10+c-'0',c=getchar();
    return s*f;
}
struct Point{
	int x,y;
	Point(int a,int b):x(a),y(b){}
    const Point operator -(const Point &r) const{
        return Point(x-r.x,y-r.y);
    }
    const int operator *(const Point &r) const{
        return x*r.y-y*r.x;
    }
};
vector<Point> p;
vector<int> v,vans;
int n,r,ans;
void dfs(int cur,int las,int sx,int sy,int sx2,int sy2){
	if(cur==n){
        int t=n*(sx2+sy2)-sx*sx-sy*sy;
		if(ans<t) ans=t,vans=v;
		return;
	}
	for(int i=las;i<p.size();i++){
		v.push_back(i);
		dfs(cur+1,i,sx+p[i].x,sy+p[i].y,sx2+p[i].x*p[i].x,sy2+p[i].y*p[i].y);
		v.pop_back();
	}
}
int main(){
	n=read(),r=read();
	rep(i,-r,0){
		p.push_back(Point(i,(int)sqrt(r*r-i*i)));
		while(p.size()>2&&(p[p.size()-2]-p[p.size()-3])*(p[p.size()-1]-p[p.size()-2])>=0){
			p[p.size()-2]=p[p.size()-1];
			p.pop_back();
		}
	}
	int s=p.size();
	repv(i,s-2,0) p.push_back(Point(-p[i].x,p[i].y));
	rep(i,1,s-1) p.push_back(Point(-p[i].x,-p[i].y));
	repv(i,s-2,1) p.push_back(Point(p[i].x,-p[i].y));
	dfs(0,0,0,0,0,0);
	printf("%d\n",ans);
	rep(i,0,n-1) printf("%d %d\n",p[vans[i]].x,p[vans[i]].y);
}


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

struct Point
{
	int x, y;
	Point operator -(Point p) {
		return {x - p.x, y - p.y};
	}
	Point operator +(Point p) {
		return {x + p.x, y + p.y};
	}
	bool operator <(Point p) const {
		return tie(x, y) < tie(p.x, p.y);
	}
	int cross(Point p) {
		return x * p.y - y * p.x;
	}
	int len2() {
		return x * x + y * y;
	}
};
vector <Point> p;
int xmul(Point a, Point b, Point c) {
	return (b - a).cross(c - a);
}

vector <Point> convex(vector <Point> v)
{
	vector <Point> r;
	sort(v.begin(), v.end());
	for(int i = 0; i < v.size(); i ++) {
		while(r.size() >= 2 && xmul(*++r.rbegin(), v[i], *r.rbegin()) >= 0)
			r.pop_back();
		r.push_back(v[i]);
	}
	int d = r.size();
	for(int i = (int)v.size() - 2; i >= 0; i --) {
		while(r.size() > d && xmul(*++r.rbegin(), v[i], *r.rbegin()) >= 0)
			r.pop_back();
		if(i != 0)
			r.push_back(v[i]);
	}
	return r;
}

int n, r;
int ans = 0;
vector <int> rec;
vector <int> now;
void dfs(int c, int pid, int sum, Point acc)
{
	if(c == n)
	{
		if(sum * n - acc.len2() > ans)
		{
			ans = sum * n - acc.len2();
			rec = now;
		}
		return;
	}
	if(pid == p.size())
		return;

	int mx = max(0, abs(acc.x) - (n - c) * r);
	int my = max(0, abs(acc.y) - (n - c) * r);
	if((sum + (n - c) * r * r * 2) * n - Point{mx, my}.len2() <= ans)
		return;
	dfs(c, pid + 1, sum, acc);
	now[c] = pid;
	dfs(c + 1, pid, sum + p[pid].len2(), acc + p[pid]);

}

int main()
{
	ios :: sync_with_stdio(false);
	cin >> n >> r;
	for(int x = -r; x <= r; x ++)
		for(int y = -r; y <= r; y ++)
			if(Point{x, y}.len2() <= r * r)
				p.push_back({x, y});
	p = convex(p);

	now.resize(n);
	dfs(0, 0, 0, {0, 0});
	cout << ans << '\n';
	for(auto &i : rec)
		cout << p[i].x << ' ' << p[i].y << '\n';
	return 0;
}


#include <cstdio>
#include <vector>
#include <string>
#include <map>
#include <unordered_map>
#include <set>
#include <queue>
#include <stack>
#include <cstring>
#include <cmath>

using namespace std;

#define pb push_back
#define all(X) X.begin(), X.end()
#define ll long long
#define forn(i, n) for (int i = 0; i < (int) n; i++)

struct elem {
  char c;
  int x;
  vector<int> Q;
  elem(char c, int x): c(c), x(x) {
  }
};

int alpha_size = 26, id_aho;

struct aho_node {
  char a;
  int x;
  vector<int> songs;
  aho_node* parent;
  aho_node* p;
  aho_node* direct_suffix;
  aho_node* children[26];

  aho_node(char a, int x, vector<int>& songs, aho_node* parent): a(a), x(x), songs(songs), parent(parent) {
    p = 0;
    direct_suffix = 0;
    memset(children, 0, sizeof(children));
  }
  aho_node(char a, int x, aho_node* parent): a(a), x(x), parent(parent) {
    p = 0;
    direct_suffix = 0;
    memset(children, 0, sizeof(children));
  }
};

vector<aho_node*> aho_nodes;

aho_node* aho_add(aho_node* x, char* S, int len, int song) {
  if (len == 0) {
    x->songs.push_back(song);
    return x;
  }
  char a = S[0];

  aho_node* child = x->children[a - 'a'];
  if (!child) {
    child = new aho_node(a, id_aho++, x);
    aho_nodes.push_back(child);
    x->children[a - 'a'] = child;
  }
  return aho_add(child, S + 1, len - 1, song);
}

void aho_direct_suffixes(aho_node *x) {
  if (x->direct_suffix) return;
  aho_node *i;
  if (x->parent) {
    aho_direct_suffixes(x->parent);

    for (i = x->parent->p; i->parent; i = i->p) {
      if (i->children[x->a - 'a']) {
        break;
      }
    }
    auto to_try = i->children[x->a - 'a'];
    if (to_try && to_try != x) {
      x->p = to_try;
    } else {
      x->p = aho_nodes[0];
    }
  } else {
    x->p = x;
  }

  if (x->p != x) {
    aho_direct_suffixes(x->p);
  }
  if (x->p != x) {
    if (x->p->songs.size() > 0) {
      x->direct_suffix = x->p;
    } else {
      x->direct_suffix = x->p->direct_suffix;
    }
  } else {
    x->direct_suffix = x;
  }
}

aho_node* aho_progress(aho_node* x, char c) {
  for (aho_node* i = x; i; i = i->p)
    if (i->children[c - 'a']) return i->children[c - 'a'];
  return aho_nodes[0];
}

#define maxn (ll) 4e5

char S[maxn + 1];

int bitin[maxn + 1], bitout[maxn + 1], T;
ll bit[maxn + 1];

void bit_init(int x, vector<vector<aho_node*>>& V) {
  bitin[x] = T++;
  for (auto e: V[x])
    bit_init(e->x, V);
  bitout[x] = T;
}

void bit_update(int x, int v, int n) {
  for (int i = x; i <= n; i += i & (-i)) {
    bit[i] += v;
  }
};

ll bit_get(int x) {
  ll ret = 0;
  for (; x; x -= x & -x) {
    ret += bit[x];
  }
  return ret;
}

ll bit_for_node(int x) {
  return -bit_get(bitin[x] - 1) + bit_get(bitout[x] - 1);
}

void go_songs(elem* x, aho_node* aho, vector<vector<elem*>>& V, vector<ll>& sol, vector<int>& to_aho) {
  if (aho->x > 0) {
    bit_update(bitin[aho->x], 1, aho_nodes.size() - 1);
  }
  for (auto q: x->Q) {
    sol[q] = bit_for_node(to_aho[q]);
  }
  for (auto e: V[x->x]) {
    aho_node* new_aho = aho_progress(aho, e->c);
    go_songs(e, new_aho, V, sol, to_aho);
  }
  if (aho->x > 0) {
    bit_update(bitin[aho->x], -1, aho_nodes.size() - 1);
  }
}

int main()
{
#ifdef DEBUG
  freopen("g.in", "r", stdin);
  freopen("g.out", "w", stdout);
#endif
  int n;
  scanf("%d", &n);

  vector<vector<elem*>> V(n + 1);
  vector<elem> wh(n + 1, elem({0, 0}));

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

  aho_node aho_root(0, id_aho++, 0);
  aho_nodes.push_back(&aho_root);

  int q;
  scanf("%d", &q);
  vector<int> to_aho(q);
  for (int i = 0; i < q; i++) {
    int song;
    scanf("%d %s", &song, S);
    auto added = aho_add(&aho_root, S, strlen(S), song);
    to_aho[i] = added->x;
    wh[song].Q.push_back(i);
  }

  for (auto e: aho_nodes) aho_direct_suffixes(e);

  vector<vector<aho_node*>> dsft(aho_nodes.size());
  for (auto e: aho_nodes) if (e->direct_suffix != e) {
    dsft[e->direct_suffix->x].push_back(e);
  }

  bit_init(0, dsft);
  vector<ll> sol(aho_nodes.size() - 1);
  go_songs(&wh[0], &aho_root, V, sol, to_aho);
  for (auto s: sol) printf("%lld\n", s);

  return 0;
}


#include <cstdio>
#include <vector>
#include <string>
#include <map>
#include <unordered_map>
#include <set>
#include <queue>
#include <stack>
#include <cstring>
#include <cmath>

using namespace std;

#define pb push_back
#define all(X) X.begin(), X.end()
#define ll long long
#define forn(i, n) for (int i = 0; i < (int) n; i++)

struct elem {
  char c;
  int x;
  vector<int> Q;
  elem(char c, int x): c(c), x(x) {
  }
};

int alpha_size = 26, id_aho;

struct aho_node {
  char a;
  int x;
  vector<int> songs;
  aho_node* parent;
  aho_node* p;
  aho_node* direct_suffix;
  aho_node* p_memo[26];
  aho_node* children[26];

  aho_node(char a, int x, vector<int>& songs, aho_node* parent): a(a), x(x), songs(songs), parent(parent) {
    p = 0;
    direct_suffix = 0;
    memset(children, 0, sizeof(children));
    memset(p_memo, 0, sizeof(p_memo));
  }
  aho_node(char a, int x, aho_node* parent): a(a), x(x), parent(parent) {
    p = 0;
    direct_suffix = 0;
    memset(children, 0, sizeof(children));
    memset(p_memo, 0, sizeof(p_memo));
  }
  ~aho_node() {
    for(int i = 0; i < alpha_size; i++) {
      if (children[i]) delete children[i];
    }
  }
};

vector<aho_node*> aho_nodes;

aho_node* aho_add(aho_node* x, char* S, int len, int song) {
  if (len == 0) {
    x->songs.push_back(song);
    return x;
  }
  char a = S[0];

  aho_node* child = x->children[a - 'a'];
  if (!child) {
    child = new aho_node(a, id_aho++, x);
    aho_nodes.push_back(child);
    x->children[a - 'a'] = child;
  }
  return aho_add(child, S + 1, len - 1, song);
}

void aho_direct_suffixes(aho_node *x) {
  if (x->direct_suffix) return;
  for (int i = 0; i < alpha_size; i++)
    if (x->children[i]) x->p_memo[i] = x;

  if (x->parent) {
    aho_direct_suffixes(x->parent);

    for (int i = 0; i < alpha_size; i++)
      if (!x->p_memo[i])
        x->p_memo[i] = x->parent->p_memo[i];

    auto to_try = x->parent->p->p_memo[x->a - 'a'];
    if (to_try && to_try->children[x->a - 'a'] != x) {
      x->p = to_try->children[x->a - 'a'];
    } else {
      x->p = aho_nodes[0];
    }
  } else {
    x->p = x;
  }

  if (x->p != x) {
    aho_direct_suffixes(x->p);
  }
  if (x->p != x) {
    if (x->p->songs.size() > 0) {
      x->direct_suffix = x->p;
    } else {
      x->direct_suffix = x->p->direct_suffix;
    }
  } else {
    x->direct_suffix = x;
  }
}

aho_node* aho_progress(aho_node* x, char c) {
  for (aho_node* i = x; i; i = i->p)
    if (i->children[c - 'a']) return i->children[c - 'a'];
  return aho_nodes[0];
}

#define maxn (ll) 4e5

char S[maxn + 1];

int bitin[maxn + 1], bitout[maxn + 1], T;
ll bit[maxn + 1];

void bit_init(int x, vector<vector<aho_node*>>& V) {
  bitin[x] = T++;
  for (auto e: V[x])
    bit_init(e->x, V);
  bitout[x] = T;
}

void bit_update(int x, int v, int n) {
  for (int i = x; i <= n; i += i & (-i)) {
    bit[i] += v;
  }
};

ll bit_get(int x) {
  ll ret = 0;
  for (; x; x -= x & -x) {
    ret += bit[x];
  }
  return ret;
}

ll bit_for_node(int x) {
  return -bit_get(bitin[x] - 1) + bit_get(bitout[x] - 1);
}

void go_songs(elem* x, aho_node* aho, vector<vector<elem*>>& V, vector<ll>& sol, vector<int>& to_aho) {
  if (aho->x > 0) {
    bit_update(bitin[aho->x], 1, aho_nodes.size() - 1);
  }
  for (auto q: x->Q) {
    sol[q] = bit_for_node(to_aho[q]);
  }
  for (auto e: V[x->x]) {
    aho_node* new_aho = aho_progress(aho, e->c);
    go_songs(e, new_aho, V, sol, to_aho);
  }
  if (aho->x > 0) {
    bit_update(bitin[aho->x], -1, aho_nodes.size() - 1);
  }
}

int main()
{
#ifdef DEBUG
  freopen("g.in", "r", stdin);
  freopen("g.out", "w", stdout);
#endif
  int n;
  scanf("%d", &n);

  vector<vector<elem*>> V(n + 1);
  vector<elem> wh(n + 1, elem({0, 0}));

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

  aho_node aho_root(0, id_aho++, 0);
  aho_nodes.push_back(&aho_root);

  int q;
  scanf("%d", &q);
  vector<int> to_aho(q);
  for (int i = 0; i < q; i++) {
    int song;
    scanf("%d %s", &song, S);
    auto added = aho_add(&aho_root, S, strlen(S), song);
    to_aho[i] = added->x;
    wh[song].Q.push_back(i);
  }

  for (auto e: aho_nodes) aho_direct_suffixes(e);

  vector<vector<aho_node*>> dsft(aho_nodes.size());
  for (auto e: aho_nodes) if (e->direct_suffix != e) {
    dsft[e->direct_suffix->x].push_back(e);
  }

  bit_init(0, dsft);
  vector<ll> sol(q);
  go_songs(&wh[0], &aho_root, V, sol, to_aho);
  for (auto s: sol) printf("%lld\n", s);

  return 0;
}


#include <cstdio>
#include <vector>
#include <string>
#include <map>
#include <unordered_map>
#include <set>
#include <queue>
#include <stack>
#include <cstring>
#include <cmath>

using namespace std;

#define pb push_back
#define all(X) X.begin(), X.end()
#define ll long long
#define forn(i, n) for (int i = 0; i < (int) n; i++)

struct elem {
  char c;
  int x;
  vector<int> Q;
  elem(char c, int x): c(c), x(x) {
  }
};

int alpha_size = 26, id_aho;

struct aho_node {
  char a;
  int x;
  vector<int> songs;
  aho_node* parent;
  aho_node* p;
  aho_node* direct_suffix;
  aho_node* p_memo[26];
  aho_node* children[26];

  aho_node(char a, int x, vector<int>& songs, aho_node* parent): a(a), x(x), songs(songs), parent(parent) {
    p = 0;
    direct_suffix = 0;
    memset(children, 0, sizeof(children));
    memset(p_memo, 0, sizeof(p_memo));
  }
  aho_node(char a, int x, aho_node* parent): a(a), x(x), parent(parent) {
    p = 0;
    direct_suffix = 0;
    memset(children, 0, sizeof(children));
    memset(p_memo, 0, sizeof(p_memo));
  }
  ~aho_node() {
    for(int i = 0; i < alpha_size; i++) {
      if (children[i]) delete children[i];
    }
  }
};

vector<aho_node*> aho_nodes;

aho_node* aho_add(aho_node* x, char* S, int len, int song) {
  if (len == 0) {
    x->songs.push_back(song);
    return x;
  }
  char a = S[0];

  aho_node* child = x->children[a - 'a'];
  if (!child) {
    child = new aho_node(a, id_aho++, x);
    aho_nodes.push_back(child);
    x->children[a - 'a'] = child;
  }
  return aho_add(child, S + 1, len - 1, song);
}

void aho_direct_suffixes(aho_node *x) {
  if (x->direct_suffix) return;
  for (int i = 0; i < alpha_size; i++)
    if (aho_nodes[0]->children[i]) x->p_memo[i] = aho_nodes[0];

  if (x->parent) {
    aho_direct_suffixes(x->parent);

    for (int i = 0; i < alpha_size; i++)
      if (!x->p_memo[i])
        x->p_memo[i] = x->parent->p_memo[i];

    auto to_try = x->parent->p->p_memo[x->a - 'a'];
    if (to_try && to_try->children[x->a - 'a'] != x) {
      x->p = to_try->children[x->a - 'a'];
    } else {
      x->p = aho_nodes[0];
    }
  } else {
    x->p = x;
  }

  if (x->p != x) {
    aho_direct_suffixes(x->p);
  }
  if (x->p != x) {
    if (x->p->songs.size() > 0) {
      x->direct_suffix = x->p;
    } else {
      x->direct_suffix = x->p->direct_suffix;
    }
  } else {
    x->direct_suffix = x;
  }
}

aho_node* aho_progress(aho_node* x, char c) {
  for (aho_node* i = x; i; i = i->p)
    if (i->children[c - 'a']) return i->children[c - 'a'];
  return aho_nodes[0];
}

#define maxn (ll) 4e5

char S[maxn + 1];

int bitin[maxn + 1], bitout[maxn + 1], T;
ll bit[maxn + 1];

void bit_init(int x, vector<vector<aho_node*>>& V) {
  bitin[x] = T++;
  for (auto e: V[x])
    bit_init(e->x, V);
  bitout[x] = T;
}

void bit_update(int x, int v, int n) {
  for (int i = x; i <= n; i += i & (-i)) {
    bit[i] += v;
  }
};

ll bit_get(int x) {
  ll ret = 0;
  for (; x; x -= x & -x) {
    ret += bit[x];
  }
  return ret;
}

ll bit_for_node(int x) {
  return -bit_get(bitin[x] - 1) + bit_get(bitout[x] - 1);
}

void go_songs(elem* x, aho_node* aho, vector<vector<elem*>>& V, vector<ll>& sol, vector<int>& to_aho) {
  if (aho->x > 0) {
    bit_update(bitin[aho->x], 1, aho_nodes.size() - 1);
  }
  for (auto q: x->Q) {
    sol[q] = bit_for_node(to_aho[q]);
  }
  for (auto e: V[x->x]) {
    aho_node* new_aho = aho_progress(aho, e->c);
    go_songs(e, new_aho, V, sol, to_aho);
  }
  if (aho->x > 0) {
    bit_update(bitin[aho->x], -1, aho_nodes.size() - 1);
  }
}

int main()
{
#ifdef DEBUG
  freopen("g.in", "r", stdin);
  freopen("g.out", "w", stdout);
#endif
  int n;
  scanf("%d", &n);

  vector<vector<elem*>> V(n + 1);
  vector<elem> wh(n + 1, elem({0, 0}));

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

  aho_node aho_root(0, id_aho++, 0);
  aho_nodes.push_back(&aho_root);

  int q;
  scanf("%d", &q);
  vector<int> to_aho(q);
  for (int i = 0; i < q; i++) {
    int song;
    scanf("%d %s", &song, S);
    auto added = aho_add(&aho_root, S, strlen(S), song);
    to_aho[i] = added->x;
    wh[song].Q.push_back(i);
  }

  for (auto e: aho_nodes) aho_direct_suffixes(e);

  vector<vector<aho_node*>> dsft(aho_nodes.size());
  for (auto e: aho_nodes) if (e->direct_suffix != e) {
    dsft[e->direct_suffix->x].push_back(e);
  }

  bit_init(0, dsft);
  vector<ll> sol(q);
  go_songs(&wh[0], &aho_root, V, sol, to_aho);
  for (auto s: sol) printf("%lld\n", s);

  return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define len(c) ((int)(c).size())
#define sqr(x) ((x)*(x))
#define pb push_back
#define PB pop_back
#define mp make_pair
#define endl '\n'
#define fi first
#define se second
typedef long long ll; typedef long double ld;
typedef vector<int> vi; typedef pair<int, int> ii;
template<class X, class Y> void amax(X &x, const Y &y){if(x < y) x = y;}
template<class X, class Y> void amin(X &x, const Y &y){if(x > y) x = y;}
const int INF = 1e9 + 10; const ll INFL = (ll)1e18 + 10;
const int MAX = 4e5 + 10;

int n, m, an, mnt;
char c[MAX], t[MAX];
int p[MAX], as[MAX], term[MAX], ts[MAX], tf[MAX], fe[MAX];
ii ap[MAX];
vi e[MAX], q[MAX], te[MAX];
int ae[MAX][26];
int apt;
int rq[MAX];

void avisit(int u){
    mnt++;
    ts[u] = mnt;
    for(auto v : te[u]) avisit(v);
    tf[u] = mnt;
}

void update(int p, int v){
    for(; p <= an; p += p & -p) fe[p] += v;
}

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

int query(int l, int r){
    return query(r) - query(l - 1);
}

void aho_corasick_push(int i){
    int v = 1;
    for(int i = 0; t[i] != '\0'; i++){
        char c = t[i];
        int cp = c - 'a';
        if(ae[v][cp] != 0) v = ae[v][cp];
        else{
            an++;
            ae[v][cp] = an;
            ap[an] = mp(v, cp);
            v = an;
        }
    }
    term[i] = v;
}

void aho_corasick(){
    queue<int> qe;
    qe.push(1);
    while(!qe.empty()){
        int u = qe.front(); qe.pop();
        if(u > 1){
            if(ap[u].fi == 1) as[u] = 1;
            else{
                int v = as[ap[u].fi];
                while(true){
                    if(ae[v][ap[u].se] != 0){
                        as[u] = ae[v][ap[u].se];
                        break;
                    }else if(v == 1){
                        as[u] = 1;
                        break;
                    }else v = as[v];
                }
            }
        }
        for(int i = 0; i < 26; i++) if(ae[u][i] != 0) qe.push(ae[u][i]);
    }

    for(int i = 2; i <= an; i++){
        te[as[i]].pb(i);
    }

    avisit(1);
}

void amove(int x){
    while(true){
        if(ae[apt][x] != 0){
            apt = ae[apt][x];
            break;
        }else if(apt == 1){
            break;
        }else apt = as[apt];
    }
}

void visit(int u){
    int bpt = apt;
    amove(c[u] - 'a');
    int pt = apt;
    update(ts[pt], 1);
    for(auto id : q[u]){
        rq[id] = query(ts[term[id]], tf[term[id]]);
    }
    for(auto v : e[u]) visit(v);
    update(ts[pt], -1);
    apt = bpt;
}

void process(){
    scanf("%d", &n);
    for(int i = 1; i <= n; i++){
        int t;
        scanf("%d", &t);
        if(t == 1){
            scanf(" %c", c + i);
        }else{
            scanf("%d %c", p + i, c + i);
            e[p[i]].pb(i);
        }
    }
    scanf("%d", &m);
    an = 1;
    for(int i = 1; i <= m; i++){
        int v;
        scanf("%d%s", &v, t);
        q[v].pb(i);
        aho_corasick_push(i);
    }

    aho_corasick();

    apt = 1;
    for(int i = 1; i <= n; i++) if(p[i] == 0) visit(i);

    for(int i = 1; i <= m; i++) printf("%d\n", rq[i]);
}

int main(){
    #ifndef ONLINE_JUDGE
    freopen("g.in", "r", stdin);
    #endif
    process();
}


#include <bits/stdc++.h>
using namespace std;
#define len(c) ((int)(c).size())
#define sqr(x) ((x)*(x))
#define pb push_back
#define PB pop_back
#define mp make_pair
#define endl '\n'
#define fi first
#define se second
typedef long long ll; typedef long double ld;
typedef vector<int> vi; typedef pair<int, int> ii;
template<class X, class Y> void amax(X &x, const Y &y){if(x < y) x = y;}
template<class X, class Y> void amin(X &x, const Y &y){if(x > y) x = y;}
const int INF = 1e9 + 10; const ll INFL = (ll)1e18 + 10;
const int MAX = 4e5 + 10;

struct aho_corasick {
    int n;
    int tme;
    int es[MAX][26];
    int term[MAX];
    int sf[MAX];
    ii par[MAX];
    ii euler[MAX];
    vi ses[MAX];
    int fl[MAX][26];
    int fe[MAX];

    aho_corasick() {
        n = 1;
    }

    void push(int id, const string &t){
        int p = 1;
        for(int i = 0; i < len(t); i++){
            int c = t[i] - 'a';
            if(es[p][c]) p = es[p][c];
            else{
                n++;
                es[p][c] = n;
                par[n] = mp(p, c);
                p = n;
            }
        }
        term[id] = p;
    }

    void build_suffix(){
        queue<int> qe;
        qe.push(1);
        while(!qe.empty()){
            int u = qe.front();
            qe.pop();

            if(par[u].fi == 1){
                sf[u] = 1;
            }else if(u != 1){
                int p = sf[par[u].fi];
                int c = par[u].se;
                while(true){
                    if(!es[p][c]){
                        if(p == 1){
                            sf[u] = 1;
                            break;
                        }
                        p = sf[p];
                    }else{
                        sf[u] = es[p][c];
                        break;
                    }
                }
            }

            for(int i = 0; i < 26; i++) if(es[u][i]) qe.push(es[u][i]);
        }
    }

    void build_tree(){
        for(int i = 2; i <= n; i++) ses[sf[i]].pb(i);
    }

    void visit_fl(int u, int p){
        for(int i = 0; i < 26; i++){
            if(es[u][i]) fl[u][i] = es[u][i];
            else if(fl[p][i]) fl[u][i] = fl[p][i];
            else fl[u][i] = 1;
        }
        for(auto v : ses[u]) visit_fl(v, u);
    }

    void build_forward(){
        visit_fl(1, 0);
    }

    void visit_euler(int u){
        euler[u].fi = ++tme;
        for(auto v : ses[u]) visit_euler(v);
        euler[u].se = tme;
    }

    void euler_tour(){
        visit_euler(1);
    }

    void update(int p, int v){
        for(; p <= n; p += p & -p) fe[p] += v;
    }

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

    int query(int l, int r){
        return query(r) - query(l - 1);
    }
} aho;

int n;
int c[MAX];
bool root[MAX];
vi es[MAX];
vi qr[MAX];
int loc;
int res[MAX];

void visit(int u){
    int ploc = loc;
    loc = aho.fl[loc][c[u]];
    aho.update(aho.euler[loc].fi, 1);

    for(int id : qr[u]){
        int x = aho.term[id];
        res[id] = aho.query(aho.euler[x].fi, aho.euler[x].se);
    }

    for(auto v : es[u]) visit(v);

    aho.update(aho.euler[loc].fi, -1);
    loc = ploc;
}

void process(){
    cin >> n;
    for(int i = 1; i <= n; i++){
        int t, p;
        char x;
        cin >> t;
        if(t == 1){
            cin >> x;
            c[i] = x - 'a';
            root[i] = true;
        }else{
            cin >> p >> x;
            c[i] = x - 'a';
            es[p].pb(i);
        }
    }

    int m;
    cin >> m;
    for(int i = 1; i <= m; i++){
        int id;
        string t;
        cin >> id >> t;
        qr[id].pb(i);
        aho.push(i, t);
    }

    aho.build_suffix();
    aho.build_tree();
    aho.build_forward();
    aho.euler_tour();

    for(int i = 1; i <= n; i++) if(root[i]){
        loc = 1;
        visit(i);
    }

    for(int i = 1; i <= m; i++) cout << res[i] << endl;
}

int main(){
    ios_base::sync_with_stdio(false);
    // cin.tie(nullptr);
    #ifndef ONLINE_JUDGE
    freopen("g.in", "r", stdin);
    #endif
    process();
}


#include <bits/stdc++.h>
using namespace std;
#define len(c) ((int)(c).size())
#define sqr(x) ((x)*(x))
#define pb push_back
#define PB pop_back
#define mp make_pair
#define endl '\n'
#define fi first
#define se second
typedef long long ll; typedef long double ld;
typedef vector<int> vi; typedef pair<int, int> ii;
template<class X, class Y> void amax(X &x, const Y &y){if(x < y) x = y;}
template<class X, class Y> void amin(X &x, const Y &y){if(x > y) x = y;}
const int INF = 1e9 + 10; const ll INFL = (ll)1e18 + 10;
const int MAX = 4e5 + 10;

int n, m, an, mnt;
char c[MAX];
int p[MAX], as[MAX], term[MAX], ts[MAX], tf[MAX], fe[MAX];
ii ap[MAX];
vi e[MAX], q[MAX], te[MAX];
string t[MAX];
int ae[MAX][26];
int apt;
int rq[MAX];

void avisit(int u){
    mnt++;
    ts[u] = mnt;
    for(auto v : te[u]) avisit(v);
    tf[u] = mnt;
}

void update(int p, int v){
    for(; p <= an; p += p & -p) fe[p] += v;
}

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

int query(int l, int r){
    return query(r) - query(l - 1);
}

void aho_corasick(){
    an = 1;
    for(int i = 1; i <= m; i++){
        int v = 1;
        for(char c : t[i]){
            int cp = c - 'a';
            if(ae[v][cp] != 0) v = ae[v][cp];
            else{
                an++;
                ae[v][cp] = an;
                ap[an] = mp(v, cp);
                v = an;
            }
        }
        term[i] = v;
    }

    queue<int> qe;
    qe.push(1);
    while(!qe.empty()){
        int u = qe.front(); qe.pop();
        if(u > 1){
            if(ap[u].fi == 1) as[u] = 1;
            else{
                int v = as[ap[u].fi];
                while(true){
                    if(ae[v][ap[u].se] != 0){
                        as[u] = ae[v][ap[u].se];
                        break;
                    }else if(v == 1){
                        as[u] = 1;
                        break;
                    }else v = as[v];
                }
            }
        }
        for(int i = 0; i < 26; i++) if(ae[u][i] != 0) qe.push(ae[u][i]);
    }

    for(int i = 2; i <= an; i++){
        te[as[i]].pb(i);
    }

    avisit(1);
}

void amove(int x){
    while(true){
        if(ae[apt][x] != 0){
            apt = ae[apt][x];
            break;
        }else if(apt == 1){
            break;
        }else apt = as[apt];
    }
}

void visit(int u){
    int bpt = apt;
    amove(c[u] - 'a');
    int pt = apt;
    update(ts[pt], 1);
    for(auto id : q[u]){
        rq[id] = query(ts[term[id]], tf[term[id]]);
    }
    for(auto v : e[u]) visit(v);
    update(ts[pt], -1);
    apt = bpt;
}

void process(){
    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];
            e[p[i]].pb(i);
        }
    }
    cin >> m;
    for(int i = 1; i <= m; i++){
        int v;
        cin >> v >> t[i];
        q[v].pb(i);
    }

    aho_corasick();

    apt = 1;
    for(int i = 1; i <= n; i++) if(p[i] == 0) visit(i);

    for(int i = 1; i <= m; i++) cout << rq[i] << endl;
}

int main(){
    ios_base::sync_with_stdio(false);
    // cin.tie(nullptr);
    #ifndef ONLINE_JUDGE
    freopen("g.in", "r", stdin);
    #endif
    process();
}


#include <bits/stdc++.h>
using namespace std;
#define len(c) ((int)(c).size())
#define sqr(x) ((x)*(x))
#define pb push_back
#define PB pop_back
#define mp make_pair
#define endl '\n'
#define fi first
#define se second
typedef long long ll; typedef long double ld;
typedef vector<int> vi; typedef pair<int, int> ii;
template<class X, class Y> void amax(X &x, const Y &y){if(x < y) x = y;}
template<class X, class Y> void amin(X &x, const Y &y){if(x > y) x = y;}
const int INF = 1e9 + 10; const ll INFL = (ll)1e18 + 10;
const int MAX = 4e5 + 10;

int n, m, an, mnt, bn;
char c[MAX];
int p[MAX], as[MAX], term[MAX], ts[MAX], tf[MAX], fe[MAX];
ii ap[MAX];
vi q[MAX], te[MAX];
string t[MAX];
int ae[MAX][26];
int apt;
int rq[MAX], bpos[MAX];
int es[MAX][26];

void avisit(int u){
    mnt++;
    ts[u] = mnt;
    for(auto v : te[u]) avisit(v);
    tf[u] = mnt;
}

void update(int p, int v){
    for(; p <= an; p += p & -p) fe[p] += v;
}

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

int query(int l, int r){
    return query(r) - query(l - 1);
}

void aho_corasick(){
    an = 1;
    for(int i = 1; i <= m; i++){
        int v = 1;
        for(char c : t[i]){
            int cp = c - 'a';
            if(ae[v][cp] != 0) v = ae[v][cp];
            else{
                an++;
                ae[v][cp] = an;
                ap[an] = mp(v, cp);
                v = an;
            }
        }
        term[i] = v;
    }

    queue<int> qe;
    qe.push(1);
    while(!qe.empty()){
        int u = qe.front(); qe.pop();
        if(u > 1){
            if(ap[u].fi == 1) as[u] = 1;
            else{
                int v = as[ap[u].fi];
                while(true){
                    if(ae[v][ap[u].se] != 0){
                        as[u] = ae[v][ap[u].se];
                        break;
                    }else if(v == 1){
                        as[u] = 1;
                        break;
                    }else v = as[v];
                }
            }
        }
        for(int i = 0; i < 26; i++) if(ae[u][i] != 0) qe.push(ae[u][i]);
    }

    for(int i = 2; i <= an; i++){
        te[as[i]].pb(i);
    }

    avisit(1);
}

void amove(int x){
    while(true){
        if(ae[apt][x] != 0){
            apt = ae[apt][x];
            break;
        }else if(apt == 1){
            break;
        }else apt = as[apt];
    }
}

void visit(int u, int cc){
    int bpt = apt;
    amove(cc);
    int pt = apt;
    update(ts[pt], 1);
    for(auto id : q[u]){
        rq[id] = query(ts[term[id]], tf[term[id]]);
    }
    for(int i = 0; i < 26; i++) if(es[u][i] != 0) visit(es[u][i], i);
    update(ts[pt], -1);
    apt = bpt;
}

void process(){
    cin >> n;
    bn = 1;
    for(int i = 1; i <= n; i++){
        int t; cin >> t;
        int pi;
        if(t == 1){
            cin >> c[i];
            pi = 1;
        }else{
            cin >> p[i] >> c[i];
            pi = bpos[p[i]];
        }
        int cc = c[i] - 'a';
        if(es[pi][cc] == 0){
            bn++;
            es[pi][cc] = bn;
        }
        bpos[i] = es[pi][cc];
    }

    cin >> m;
    for(int i = 1; i <= m; i++){
        int v;
        cin >> v >> t[i];
        q[bpos[v]].pb(i);
    }

    aho_corasick();

    apt = 1;
    for(int i = 0; i < 26; i++) if(es[1][i] != 0) visit(es[1][i], i);

    for(int i = 1; i <= m; i++) cout << rq[i] << endl;
}

int main(){
    ios_base::sync_with_stdio(false);
    // cin.tie(nullptr);
    #ifndef ONLINE_JUDGE
    freopen("g.in", "r", stdin);
    #endif
    process();
}


#include <bits/stdc++.h>
using namespace std;
namespace treeArr {
    int sum[400010];
    inline void add(int x, int k) {
        for(; x <= 400000; x += x & -x) sum[x] += k;
    }
    inline int get(int x) {
        int ans = 0;
        for(; x; x -= x & -x) ans += sum[x];
        return ans;
    }
}
namespace AC {
    int son[400010][26], cnt;
    int fail[400010];
    vector<int> e[400010];
    int dfn[400010], sze[400010];
    int dfsnow;
    inline int add(char *s) {
        int now = 0;
        for(int i = 0, n = strlen(s); i < n; i++) {
            if(son[now][s[i] - 'a'] == 0) son[now][s[i] - 'a'] = ++cnt;
            now = son[now][s[i] - 'a'];
        }
        return now;
    }
    inline int getans(int id) {
        return treeArr :: get(dfn[id] + sze[id] - 1) - treeArr :: get(dfn[id] - 1);
    }
    inline void dfs(int now) {
        dfn[now] = ++dfsnow;
        sze[now] = 1;
        for(auto i : e[now]) dfs(i), sze[now] += sze[i];
    }
    inline void build() {
        queue<int> q;
        for(int i = 0; i < 26; i++) if(son[0][i]) q.push(son[0][i]);
        while(!q.empty()) {
            int now = q.front();
            q.pop();
            e[fail[now]].push_back(now);
            for(int i = 0; i < 26; i++) {
                if(son[now][i]) fail[son[now][i]] = son[fail[now]][i], q.push(son[now][i]);
                else son[now][i] = son[fail[now]][i];
            }
        }
        dfs(0);
    }
    inline int f(int x, int k) {
        return son[x][k - 'a'];
    }
}
char c[400010];
int opt[400010];
vector<int> son[400010];
int ans[400010];
vector<pair<int, int> > que[400010];
void dfs(int now, int nowd) {
    nowd = AC :: f(nowd, c[now]);
    treeArr :: add(AC :: dfn[nowd], 1);
    for(auto i : son[now]) dfs(i, nowd);
    for(auto i : que[now]) {
        ans[i.second] = AC :: getans(i.first);
    }
    treeArr :: add(AC :: dfn[nowd], -1);
}
char s[400010];
int main() {
    int n;
    scanf("%d", &n);
    for(int i = 1, fa; i <= n; i++) {
        scanf("%d", opt + i);
        if(opt[i] == 2) scanf("%d", &fa), son[fa].push_back(i);
        scanf("%s", c + i);
    }
    int m;
    scanf("%d", &m);
    for(int i = 1; i <= m; i++) {
        int id;
        scanf("%d%s", &id, s);
        que[id].push_back(make_pair(AC :: add(s), i));
    }
    AC :: build();
    for(int i = 1; i <= n; i++) if(opt[i] == 1) dfs(i, 0);
    for(int i = 1; i <= m; i++) printf("%d\n", ans[i]);
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define oo 1000000000
#define mod 998244353
const int N = 400010 , LOG = 19;
int base = 31;
int n , m , t , hsh[N] , p , idx[N] , inv[N] , po[N];
int dp[LOG][N] , depth[N] , ans[N] , Val[LOG][N];
char x[N];
vector< int > v;
int fres = 1;

int seg[4 * N];

int sum[N];

int Idx , val;

int update(int s,int e,int idx){
    if(s > Idx || e < Idx)
        return seg[idx];
    if(s == e)
        return seg[idx] = val;
    return seg[idx] = update(s,((s+e) >> 1),(idx << 1)) + update(((s+e) >> 1) + 1,e,(idx << 1) + 1);
}

int l, r;

int getsum(int s,int e,int idx){
    if(s > r || e < l)
        return 0;
    if(s >= l && e <= r)
        return seg[idx];
    return getsum(s,((s+e) >> 1),(idx << 1)) + getsum(((s+e) >> 1) + 1,e,(idx << 1) + 1);
}

string s;

vector< int > T[N];

vector< pair<string,int> > g[N];

inline int fastpower(int num,int po){
    fres = 1;
    while(po > 0){
        if(po & 1)
            fres = (long long)fres * num % mod;
        po >>= 1;
        num = (long long)num * num % mod;
    }
    return fres;
}

inline int get_hash(int a,int b){
    return ((((long long)(hsh[a] - hsh[b]) * inv[depth[b]] % mod) + mod) % mod);
}

inline int get_hash2(int i,int j,int sz){
    j++;
    return ((((long long)(sum[i] - sum[j]) * inv[sz - j] % mod) + mod) % mod);
}

inline bool comp(int a,int b){
    for(int k = LOG - 1;k>=0;k--){
        if(dp[k][a] == -1 || dp[k][a] == -1) continue;
        if(Val[k][a] == Val[k][b])
            a = dp[k][a] , b = dp[k][b];
    }
    if(a != b && x[a] < x[b])
        return true;
    return false;
}

string get_string(int node){
    string res ;
    while(node != 0){
        res += x[node];
        node = dp[0][node];
    }
    return res;
}

char tmpread[N];

inline void read(string &s){
    scanf("%s",tmpread);
    s = (string)tmpread;
}

inline bool comp2(int a,string &s){
    int b = 0;
    for(int k = LOG - 1;k>=0;k--){
        if(dp[k][a] == -1 || b + (1 << k) > (int)s.size()) continue;
        if(Val[k][a] == get_hash2(b ,b + (1 << k) - 1,(int)s.size()))
            a = dp[k][a] , b += (1 << k);
    }
    if(b == (int)s.size() || s[b] < x[a])
        return true;
    return false;
}

inline bool comp3(int a,string &s){
    int b = 0;
    for(int k = LOG - 1;k>=0;k--){
        if(dp[k][a] == -1 || b + (1 << k) > (int)s.size()) continue;
        if(Val[k][a] == get_hash2(b , b + (1 << k) - 1,(int)s.size()))
            a = dp[k][a] , b += (1 << k);
    }
    return (b == (int)s.size());
}

int low , high , res , mid;

inline int get(string &s){
    sum[(int)s.size()] = 0;
    for(int i = (int)s.size() - 1 ;i >=0 ;i--){
        sum[i] = (long long)(s[i] - 'a' + 1) * po[(int)s.size() - i] % mod;
        sum[i] += sum[i + 1];
        if(sum[i] >= mod)
            sum[i] -= mod;
    }
    low = 0 , high = (int)v.size() -1 , res = (int)v.size() , mid;
    while(high >= low){
        mid = ((low + high) >> 1);
        if(comp2(v[mid] , s))
            res = mid , high = mid - 1;
        else
            low = mid + 1;
    }
    if(res == (int)v.size()) return 0;
    l = res;
    low = res , high = (int)v.size() - 1 , res = low - 1;
    while(high >= low){
        mid = ((low + high) >> 1);
        if(comp3(v[mid] , s))
            res = mid , low = mid + 1;
        else
            high = mid - 1;
    }
    r = res;
    if(r >= l)
        return getsum(0 , (int)v.size() - 1 , 1);
    return 0;
}

void DFS(int node){
    if(node != 0){
        Idx = idx[node];
        val = 1;
        update(0 , (int)v.size() - 1, 1);
    }
    for(int i = 0 ;i < (int)g[node].size();i++){
        ans[g[node][i].second] = get(g[node][i].first);
    }
    for(int i = 0 ;i < (int)T[node].size();i++){
        DFS(T[node][i]);
    }
    if(node != 0){
        Idx = idx[node];
        val = 0;
        update(0 , (int)v.size() - 1, 1);
    }
}

int main(){
    po[0] = 1;
    for(int i = 1;i < N;i++){
        po[i] = (long long)po[i - 1] * base % mod;
    }
    for(int i = 0; i < N;i++){
        inv[i] = fastpower(po[i] , mod - 2);
    }
    scanf("%d",&n);
    v.resize(n);
    for(int k = 0 ; k < LOG ;k++) dp[k][0] = -1;
    for(int i = 1;i <= n;i++){
        v[i - 1] = i;
        scanf("%d",&t);
        if(t == 1){
            scanf(" %c",&x[i]);
            hsh[i] = (x[i] - 'a' + 1) * base;
            T[0].push_back(i);
            dp[0][i] = 0;
            Val[0][i] = (long long)(hsh[i] - hsh[dp[0][i]]) * inv[depth[dp[0][i]]] % mod;
            if(Val[0][i] < 0) Val[0][i] += mod;
            for(int k = 1 ; k < LOG ;k++)
                dp[k][i] = -1;
            depth[i] = 1;
        }
        else{
            scanf("%d %c",&p,&x[i]);
            T[p].push_back(i);
            dp[0][i] = p;
            depth[i] = depth[p] + 1;
            hsh[i] = (hsh[p] + ((long long)(x[i] - 'a' + 1) * po[depth[i]] % mod)) % mod;
            Val[0][i] = (long long)(hsh[i] - hsh[dp[0][i]]) * inv[depth[dp[0][i]]] % mod;
            if(Val[0][i] < 0) Val[0][i] += mod;
            for(int k = 1 ; k < LOG ;k++){
                if(dp[k - 1][i] == -1)
                    dp[k][i] = -1;
                else{
                    dp[k][i] = dp[k - 1][dp[k - 1][i]];
                    Val[k][i] = (long long)(hsh[i] - hsh[dp[k][i]]) * inv[depth[dp[k][i]]] % mod;
                    if(Val[k][i] < 0) Val[k][i] += mod;
                }
            }
        }
    }
    sort(v.begin(),v.end(),comp);
    for(int i = 0 ;i < (int)v.size();i++){
        idx[v[i]] = i;
    }
    int q;
    scanf("%d",&q);
    for(int i = 0 ;i < q;i++){
        scanf("%d",&p);
        read(s);
        reverse(s.begin(),s.end());
        g[p].push_back(make_pair(s,i));
    }
    DFS(0);
    for(int i = 0 ;i < q;i++){
        printf("%d\n",ans[i]);
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
namespace treeArr {
	int sum[400010];
	inline void add(int x, int k) {
		for(; x <= 400000; x += x & -x) sum[x] += k;
	}
	inline int get(int x) {
		int ans = 0;
		for(; x; x -= x & -x) ans += sum[x];
		return ans;
	}
}
namespace AC {
	int son[400010][26], cnt;
	int fail[400010];
	vector<int> e[400010];
	int dfn[400010], sze[400010];
	int dfsnow;
	inline int add(char *s) {
		int now = 0;
		for(int i = 0, n = strlen(s); i < n; i++) {
			if(son[now][s[i] - 'a'] == 0) son[now][s[i] - 'a'] = ++cnt;
			now = son[now][s[i] - 'a'];
		}
		return now;
	}
	inline int getans(int id) {
		return treeArr :: get(dfn[id] + sze[id] - 1) - treeArr :: get(dfn[id] - 1);
	}
	inline void dfs(int now) {
		dfn[now] = ++dfsnow;
		sze[now] = 1;
		for(auto i : e[now]) dfs(i), sze[now] += sze[i];
	}
	inline void build() {
		queue<int> q;
		for(int i = 0; i < 26; i++) if(son[0][i]) q.push(son[0][i]);
		while(!q.empty()) {
			int now = q.front();
			q.pop();
			e[fail[now]].push_back(now);
			for(int i = 0; i < 26; i++) {
				if(son[now][i]) fail[son[now][i]] = son[fail[now]][i], q.push(son[now][i]);
				else son[now][i] = son[fail[now]][i];
			}
		}
		dfs(0);
	}
	inline int f(int x, int k) {
		return son[x][k - 'a'];
	}
}
char c[400010];
int opt[400010];
vector<int> son[400010];
int ans[400010];
vector<pair<int, int> > que[400010];
void dfs(int now, int nowd) {
	nowd = AC :: f(nowd, c[now]);
	treeArr :: add(AC :: dfn[nowd], 1);
	for(auto i : son[now]) dfs(i, nowd);
	for(auto i : que[now]) {
		ans[i.second] = AC :: getans(i.first);
	}
	treeArr :: add(AC :: dfn[nowd], -1);
}
char s[400010];
int main() {
	int n;
	scanf("%d", &n);
	for(int i = 1, fa; i <= n; i++) {
		scanf("%d", opt + i);
		if(opt[i] == 2) scanf("%d", &fa), son[fa].push_back(i);
		scanf("%s", c + i);
	}
	int m;
	scanf("%d", &m);
	for(int i = 1; i <= m; i++) {
		int id;
		scanf("%d%s", &id, s);
		que[id].push_back(make_pair(AC :: add(s), i));
	}
	AC :: build();
	for(int i = 1; i <= n; i++) if(opt[i] == 1) dfs(i, 0);
	for(int i = 1; i <= m; i++) printf("%d\n", ans[i]);
	return 0;
}


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

const int N = (int)5e5 + 7;

int n, m;
int Rt = 1, ch[N][26], trie_cnt = 1;
int pos[N];
int ans[N];
char s[N];

vector<pair<int, int>> V[N], Q[N];
vector<int> G[N];

struct Bit {
    int a[N];
    inline void modify(int x, int v) {
        for(int i = x; i < N; i += i & -i) {
            a[i] += v;
        }
    }
    inline int sum(int x) {
        int ans = 0;
        for(int i = x; i; i -= i & -i) {
            ans += a[i];
        }
        return ans;
    }
} bit;

inline int ID(char c) {
    return c - 'a';
}

int in[N], ot[N], dfs_clock;

void dfs(int u) {
    in[u] = ++dfs_clock;
    for(int i = 0; i < 26; i++) {
        if(!ch[u][i]) continue;
        dfs(ch[u][i]);
    }
    ot[u] = dfs_clock;
}

struct Ac {
    // 1. init before use
    // 2. check character set
    // 3. use build
    int ch[N][26], f[N], tot, sz, subVal;
    inline int newNode() {
        tot++; f[tot] = 0;
        memset(ch[tot], 0, sizeof(ch[tot]));
        return tot;
    }
    void init(int _sz, int _subVal) {
        sz = _sz; subVal = _subVal;
        tot = -1; newNode();
    }
    inline int idx(int c) {return c - subVal;}
    int addStr(char* s) {
        int u = 0;
        for(int i = 0; s[i]; i++) {
            int c = idx(s[i]);
            if(!ch[u][c]) ch[u][c] = newNode();
            u = ch[u][c];
        }
        return u;
    }
    void build() {
        queue<int> que;
        for(int c = 0; c < sz; c++) {
            int v = ch[0][c];
            if(!v) ch[0][c] = 0;
            else f[v] = 0, que.push(v);
        }
        while(!que.empty()) {
            int u = que.front(); que.pop();
            for(int c = 0; c < sz; c++) {
                int v = ch[u][c];
                if(!v) ch[u][c] = ch[f[u]][c];
                else f[v] = ch[f[u]][c], que.push(v);
            }
        }
    }
    void getGraph() {
        for(int i = 1; i <= tot; i++) {
            G[f[i]].push_back(i);
        }
    }
} ac;

void go(int u, int cur) {
    V[cur].push_back(make_pair(in[u], ot[u]));
    for(int i = 0; i < 26; i++) {
        if(!ch[u][i]) continue;
        go(ch[u][i], ac.ch[cur][i]);
    }
}

int son[N], sz[N];

void gao(int u) {
    son[u] = -1;
    sz[u] = 1;
    for(auto &v : G[u]) {
        gao(v);
        sz[u] += sz[v];
        if(son[u] == -1 || sz[v] > sz[son[u]]) {
            son[u] = v;
        }
    }
}

void flip(int u, int op) {
    for(auto &t : V[u]) {
        bit.modify(t.first, op);
        bit.modify(t.second + 1, -op);
    }
}

void modify(int u, int op) {
    flip(u, op);
    for(auto &v : G[u]) {
        modify(v, op);
    }
}

void solve(int u, bool keep) {
    for(auto &v : G[u]) {
        if(v == son[u]) continue;
        solve(v, false);
    }
    if(son[u]) solve(son[u], true);
    for(auto &v : G[u]) {
        if(v == son[u]) continue;
        modify(v, 1);
    }
    flip(u, 1);
    for(auto &q : Q[u]) {
        ans[q.second] = bit.sum(q.first);
    }
    if(!keep) {
        modify(u, -1);
    }
}

int main() {
    ac.init(26, 'a');
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) {
        int op; scanf("%d", &op);
        if(op == 1) {
            char c[4];
            scanf("%s", c);
            if(!ch[Rt][ID(*c)]) ch[Rt][ID(*c)] = ++trie_cnt;
            pos[i] = ch[Rt][ID(*c)];
        }
        else {
            int j; char c[4];
            scanf("%d%s", &j, c);
            int cur = pos[j];
            if(!ch[cur][ID(*c)]) ch[cur][ID(*c)] = ++trie_cnt;
            pos[i] = ch[cur][ID(*c)];
        }
    }
    dfs(Rt);
    scanf("%d", &m);
    for(int i = 1; i <= m; i++) {
        int x; scanf("%d", &x);
        scanf("%s", s);
        int p = ac.addStr(s);
        Q[p].push_back(make_pair(in[pos[x]], i));
    }
    ac.build();
    go(Rt, 0);
    ac.getGraph();
    gao(0);
    solve(0, false);
    for(int i = 1; i <= m; i++) {
        printf("%d\n", ans[i]);
    }
    return 0;
}

/**
**/


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

const int N = (int)5e5 + 7;

int n, m;
int Rt = 1, ch[N][26], trie_cnt = 1;
int pos[N];
int ans[N];
char s[N];

vector<pair<int, int>> V[N], Q[N];
vector<int> G[N];

struct Bit {
    int a[N];
    inline void modify(int x, int v) {
        for(int i = x; i < N; i += i & -i) {
            a[i] += v;
        }
    }
    inline int sum(int x) {
        int ans = 0;
        for(int i = x; i; i -= i & -i) {
            ans += a[i];
        }
        return ans;
    }
} bit;

inline int ID(char c) {
    return c - 'a';
}

int in[N], ot[N], dfs_clock;

void dfs(int u) {
    in[u] = ++dfs_clock;
    for(int i = 0; i < 26; i++) {
        if(!ch[u][i]) continue;
        dfs(ch[u][i]);
    }
    ot[u] = dfs_clock;
}

struct Ac {
    // 1. init before use
    // 2. check character set
    // 3. use build
    int ch[N][26], f[N], tot, sz, subVal;
    inline int newNode() {
        tot++; f[tot] = 0;
        memset(ch[tot], 0, sizeof(ch[tot]));
        return tot;
    }
    void init(int _sz, int _subVal) {
        sz = _sz; subVal = _subVal;
        tot = -1; newNode();
    }
    inline int idx(int c) {return c - subVal;}
    int addStr(char* s) {
        int u = 0;
        for(int i = 0; s[i]; i++) {
            int c = idx(s[i]);
            if(!ch[u][c]) ch[u][c] = newNode();
            u = ch[u][c];
        }
        return u;
    }
    void build() {
        queue<int> que;
        for(int c = 0; c < sz; c++) {
            int v = ch[0][c];
            if(!v) ch[0][c] = 0;
            else f[v] = 0, que.push(v);
        }
        while(!que.empty()) {
            int u = que.front(); que.pop();
            for(int c = 0; c < sz; c++) {
                int v = ch[u][c];
                if(!v) ch[u][c] = ch[f[u]][c];
                else f[v] = ch[f[u]][c], que.push(v);
            }
        }
    }
    void getGraph() {
        for(int i = 1; i <= tot; i++) {
            G[f[i]].push_back(i);
        }
    }
} ac;

void go(int u, int cur) {
    V[cur].push_back(make_pair(in[u], ot[u]));
    for(int i = 0; i < 26; i++) {
        if(!ch[u][i]) continue;
        go(ch[u][i], ac.ch[cur][i]);
    }
}

int son[N], sz[N];

void gao(int u) {
    son[u] = -1;
    sz[u] = 1;
    for(auto &v : G[u]) {
        gao(v);
        sz[u] += sz[v];
        if(son[u] == -1 || sz[v] > sz[son[u]]) {
            son[u] = v;
        }
    }
}

void flip(int u, int op) {
    for(auto &t : V[u]) {
        bit.modify(t.first, op);
        bit.modify(t.second + 1, -op);
    }
}

void modify(int u, int op) {
    flip(u, op);
    for(auto &v : G[u]) {
        modify(v, op);
    }
}

void solve(int u, bool keep) {
    for(auto &v : G[u]) {
        if(v == son[u]) continue;
        solve(v, false);
    }
    if(son[u]) solve(son[u], true);
    for(auto &v : G[u]) {
        if(v == son[u]) continue;
        modify(v, 1);
    }
    flip(u, 1);
    for(auto &q : Q[u]) {
        ans[q.second] = bit.sum(q.first);
    }
    if(!keep) {
        modify(u, -1);
    }
}

int main() {
    ac.init(26, 'a');
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) {
        int op; scanf("%d", &op);
        if(op == 1) {
            char c[4];
            scanf("%s", c);
            if(!ch[Rt][ID(*c)]) ch[Rt][ID(*c)] = ++trie_cnt;
            pos[i] = ch[Rt][ID(*c)];
        }
        else {
            int j; char c[4];
            scanf("%d%s", &j, c);
            int cur = pos[j];
            if(!ch[cur][ID(*c)]) ch[cur][ID(*c)] = ++trie_cnt;
            pos[i] = ch[cur][ID(*c)];
        }
    }
    dfs(Rt);
    scanf("%d", &m);
    for(int i = 1; i <= m; i++) {
        int x; scanf("%d", &x);
        scanf("%s", s);
        int p = ac.addStr(s);
        Q[p].push_back(make_pair(pos[x], i));
    }
    ac.build();
    go(Rt, 0);
    ac.getGraph();
    gao(0);
    solve(0, false);
    for(int i = 1; i <= m; i++) {
        printf("%d\n", ans[i]);
    }
    return 0;
}

/**
**/


#include<bits/stdc++.h>
#define pi pair<int, int>
#define mk make_pair
#define low(x) x&-x
using namespace std;
const int maxn = 4e5 + 10;
int ans[maxn], C[maxn], L[maxn * 26], R[maxn * 26], cnt;
void up(int x, int v) {
    //if (!x)
        //return;
    for (; x <= cnt; x += low(x))
        C[x] += v;
}
int qu(int x) {
    int res = 0;
    for (; x; x -= low(x))
        res += C[x];
    return res;
}
struct tri {
    vector<int> G[maxn];
    int ch[maxn][26], f[maxn * 26], sz;
    int insert(char *s) {
        int o = 0;
        for (int i = 0; s[i]; i++) {
            int c = s[i] - 'a';
            if (!ch[o][c])
                ch[o][c] = ++sz;
            o = ch[o][c];
        }
        return o;
    }
    void dfs(int o) {
        L[o] = ++cnt;
        for (auto v : G[o])
            dfs(v);
        R[o] = cnt;
    }
    queue<int> q;
    void build() {
        int o = 0;
        for (int i = 0; i < 26; i++)
            if (ch[o][i])
                q.push(ch[o][i]);
        while (!q.empty()) {
            o = q.front();
            q.pop();
            for (int i = 0; i < 26; i++) {
                int v = ch[o][i];
                if (v) {
                    q.push(v);
                    f[v] = ch[f[o]][i];
                }
                else
                    ch[o][i] = ch[f[o]][i];
            }
        }
        for (int i = 1; i <= sz; i++)
            G[f[i]].push_back(i);
        dfs(0);
    }
} ac;
vector<int> G[maxn];
vector<pi> qry[maxn];
int opt[maxn];
char s[maxn], c[maxn];
void gao(int x, int o) {
    o = ac.ch[o][c[x] - 'a'];
    //printf("x = %d o = %d\n", x, o);
    up(L[o], 1);
    for (auto tmp : qry[x])
        ans[tmp.second] = qu(R[tmp.first]) - qu(L[tmp.first] - 1);
    for (auto v : G[x])
        gao(v, o);
    up(L[o], -1);
}
int main() {
    int n, x, q;
    cin>>n;
    for (int i = 1; i <= n; i++) {
        cin>>opt[i];
        if (opt[i] == 1)
            cin>>c[i];
        else {
            cin>>x>>c[i];
            G[x].push_back(i);
        }
    }
    cin>>q;
    for (int i = 1; i <= q; i++) {
        cin>>x>>s;
        qry[x].push_back(mk(ac.insert(s), i));
    }
    ac.build();
    for (int i = 1; i <= n; i++)
        if (opt[i] == 1)
            gao(i, 0);
    for (int i = 1; i <= q; i++)
        printf("%d\n", ans[i]);
}


#include<bits/stdc++.h>
#define pi pair<int, int>
#define mk make_pair
#define low(x) x&-x
using namespace std;
const int maxn = 4e5 + 10;
int ans[maxn], C[maxn], L[maxn * 26], R[maxn * 26], cnt;
void up(int x, int v) {
    if (!x)
        return;
    for (; x <= cnt; x += low(x))
        C[x] += v;
}
int qu(int x) {
    int res = 0;
    for (; x; x -= low(x))
        res += C[x];
    return res;
}
struct tri {
    vector<int> G[maxn];
    int ch[maxn][26], f[maxn * 26], sz;
    int insert(char *s) {
        int o = 0;
        for (int i = 0; s[i]; i++) {
            int c = s[i] - 'a';
            if (!ch[o][c])
                ch[o][c] = ++sz;
            o = ch[o][c];
        }
        return o;
    }
    void dfs(int o) {
        L[o] = ++cnt;
        for (auto v : G[o])
            dfs(v);
        R[o] = cnt;
    }
    queue<int> q;
    void build() {
        int o = 0;
        for (int i = 0; i < 26; i++)
            if (ch[o][i])
                q.push(ch[o][i]);
        while (!q.empty()) {
            o = q.front();
            q.pop();
            for (int i = 0; i < 26; i++) {
                int v = ch[o][i];
                if (v) {
                    q.push(v);
                    f[v] = ch[f[o]][i];
                }
                else
                    ch[o][i] = ch[f[o]][i];
            }
        }
        for (int i = 1; i <= sz; i++)
            G[f[i]].push_back(i);
        dfs(0);
    }
} ac;
vector<int> G[maxn];
vector<pi> qry[maxn];
int opt[maxn];
char s[maxn], c[maxn];
void gao(int x, int o) {
    o = ac.ch[o][c[x] - 'a'];
    up(L[o], 1);
    for (auto tmp : qry[x])
        ans[tmp.second] = qu(R[tmp.first]) - qu(L[tmp.first] - 1);
    for (auto v : G[x])
        gao(v, o);
    up(L[o], -1);
}
int main() {
    int n, x, q;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &opt[i]);
        if (opt[i] == 1)
            scanf(" %c", &c[i]);
        else {
            scanf("%d %c", &x, &c[i]);
            G[x].push_back(i);
        }
    }
    scanf("%d", &q);
    for (int i = 1; i <= q; i++) {
        scanf("%d%s", &x, s);
        qry[x].push_back(mk(ac.insert(s), i));
    }
    ac.build();
    for (int i = 1; i <= n; i++)
        if (opt[i] == 1)
            gao(i, 0);
    for (int i = 1; i <= q; i++)
        printf("%d\n", ans[i]);
}


#include <bits/stdc++.h>
#ifndef ONLINE_JUDGE
#define debug(fmt, ...) fprintf(stderr, "[%s] " fmt "\n", __func__, ##__VA_ARGS__)
#else
#define debug(...)
#endif

const int maxn = 1 << 19;
int op[maxn];
char c[maxn];

struct Trie
{
    int ch[maxn][26], f[maxn];
    int sz, rt;
    int newnode()
    {
        memset(ch[sz], -1, sizeof(ch[sz]));
        return sz++;
    }
    void init() { sz = 0, rt = newnode(); }
    inline int idx(char c) { return c - 'a'; };
    int insert(const char* s)
    {
        int u = 0;
        for (int i = 0; s[i]; i++)
        {
            int c = idx(s[i]);
            if (ch[u][c] == -1) ch[u][c] = newnode();
            u = ch[u][c];
        }
        return u;
    }
    std::vector<int> g[maxn];
    int dfn;
    int in[maxn], out[maxn];
    void build()
    {
        std::queue<int> q;
        f[rt] = rt;
        for (int c = 0; c < 26; c++)
        {
            if (~ch[rt][c])
                f[ch[rt][c]] = rt, q.push(ch[rt][c]);
            else
                ch[rt][c] = rt;
        }
        while (!q.empty())
        {
            int u = q.front();
            q.pop();
            for (int c = 0; c < 26; c++)
            {
                if (~ch[u][c])
                    f[ch[u][c]] = ch[f[u]][c], q.push(ch[u][c]);
                else
                    ch[u][c] = ch[f[u]][c];
            }
        }
        for (int i = 1; i < sz; i++) g[f[i]].push_back(i);
        dfn = 0;
        dfs(rt);
    }
    void dfs(int u)
    {
        in[u] = ++dfn;
        for (auto v : g[u]) dfs(v);
        out[u] = dfn;
    }

} ac;
std::vector<int> g[maxn];
template <class T, int N>
class BIT
{
private:
    T data[N];

public:
    BIT() {}
    void update(int x, T v)
    {
        for (int i = x; i < N; i += i & -i) data[i] += v;
    }

    T query(int l, int r)
    {
        T ret = 0;
        for (int i = r; i; i -= i & -i) ret += data[i];
        for (int i = l - 1; i; i -= i & -i) ret -= data[i];
        return ret;
    }
};

BIT<int, maxn> bit;

std::vector<std::pair<int, int>> query[maxn];
int ans[maxn];

void dfs(int i, int u)
{
    int v = ac.ch[u][c[i] - 'a'];
    bit.update(ac.in[v], 1);
    for (auto q : query[i]) ans[q.second] = bit.query(ac.in[q.first], ac.out[q.first]);
    for (auto j : g[i]) dfs(j, v);
    bit.update(ac.in[v], -1);
}

int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int n;
    std::cin >> n;
    for (int i = 1, x; i <= n; i++)
    {
        std::cin >> op[i];
        if (op[i] == 1)
            std::cin >> c[i];
        else
        {
            std::cin >> x >> c[i];
            g[x].push_back(i);
        }
    }
    ac.init();
    int q;
    std::cin >> q;
    std::string s;
    for (int i = 0, x; i < q; i++)
    {
        std::cin >> x >> s;
        query[x].emplace_back(ac.insert(s.c_str()), i);
    }
    ac.build();
    for (int i = 1; i <= n; i++)
        if (op[i] == 1) dfs(i, ac.rt);
    for (int i = 0; i < q; i++) std::cout << ans[i] << '\n';
}


#include <bits/stdc++.h>

using namespace std;

#define MN 400100
#define ALP 26

int C(char c) { return c - 'a'; }

struct jonson {
    jonson* child[ALP];
    vector<pair<int, int>> queries;

    jonson() {
        for(int i = 0; i < ALP; i++)
            child[i] = NULL;
    }
} *wilson;

int n, m, ans[MN], final_ans[MN];
jonson* rev[MN];
char s[MN];
set<string> klebin;

struct aho {
    int parent[MN], suffix[MN], transition[MN][ALP], super[MN];
    char from[MN];
    int id[MN], cnt, built;
    long long ending[MN], lazy[MN];

    int new_node(int _parent = 0, char _from = ' ') {
        parent[cnt] = _parent; from[cnt] = _from; id[cnt] = -1;
        suffix[cnt] = super[cnt] = ending[cnt] = lazy[cnt] = 0;
        for(int i = 0; i < ALP; i++) transition[cnt][i] = 0;
        return cnt++;
    }

    aho() {
        cnt = built = 0;
        new_node();
    }

    int add_word(string &word, int _id = 0) {
        int node = 0;
        for(int i = 0; i < word.size(); i++) {
            int nxt = C(word[i]);
            if(!transition[node][nxt]) transition[node][nxt] = new_node(node, word[i]);
            node = transition[node][nxt];
        }
        ending[node]++;
        if(id[node] == -1) id[node] = _id;
        return id[node];
    }

    void build() {
        built = 1;
        queue<int> q;
        for(int i = 0; i < ALP; i++)
            if(transition[0][i]) q.push(transition[0][i]);

        while(!q.empty()) {
            int v = q.front(); q.pop();
            if(parent[v]) suffix[v] = transition[suffix[parent[v]]][C(from[v])];

            if(id[v] != -1) super[v] = v;
            else super[v] = super[suffix[v]];

            ending[v] += ending[suffix[v]];
            for(int i = 0; i < ALP; i++) {
                if(!transition[v][i]) transition[v][i] = transition[suffix[v]][i];
                else q.push(transition[v][i]);
            }
        }
    }

    void search_text(jonson* node, int *ans, int where = 0) {
        if(!built) build();
        int prefix;

        for(int i = 0; i < ALP; i++) {
            jonson* nxt = node->child[i];
            if(!nxt) continue;

            prefix = transition[where][i];
            for(int u = super[prefix]; u; u = super[suffix[u]])
                ans[id[u]]++;

            for(auto x : nxt->queries) {
                final_ans[x.first] = ans[x.second];
            }

            search_text(nxt, ans, prefix);
            for(int u = super[prefix]; u; u = super[suffix[u]])
                ans[id[u]]--;
        }
    }
} dict;

int main() {
    wilson = new jonson();
    rev[0] = wilson;

    scanf("%d", &n);
    for(int i = 1; i <= n; i++) {
        int t, j; char c;
        scanf("%d", &t);
        if(t == 1) {
            scanf(" %c", &c);
            j = 0;
        } else if(t == 2) {
            scanf("%d %c", &j, &c);
        } else assert(false);

        jonson* tmp = rev[j];
        if(tmp->child[C(c)] == NULL)
            tmp->child[C(c)] = new jonson();

        rev[i] = tmp->child[C(c)];
    }

    scanf("%d", &m);
    for(int i = 1; i <= m; i++) {
        int x; string str;
        scanf("%d %s", &x, s);
        str = s;

        int id = dict.add_word(str, klebin.size());
        rev[x]->queries.emplace_back(i, id);
        klebin.insert(str);
    }

    dict.search_text(wilson, ans);
    for(int i = 1; i <= m; i++) {
        printf("%d\n", final_ans[i]);
    }

    return 0;
}


#include<bits/stdc++.h>
using namespace std;const int N=4e5+7;
struct data{int to,next,v;}e[N<<1];int ans[N],a[N][26],nxt[N],bit[N],sz=1,ind,n,m,i,j,t,w,q[N],cnt,L[N],R[N],root[N],op;char s[N],ch;vector<int> v[N];
struct graph{
	int head[N];
	void ins(int u,int v,int w=0){e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;e[cnt].v=w;}
}g1,g2;
int A(int x,int val){while(x<=ind)bit[x]+=val,x+=x&-x;}
int Q(int x,int res=0){while(x)res+=bit[x],x-=x&-x;return res;}
void ins(int id){
	int now=1;for(int i=0,c;s[i];++i){
		c=s[i]-'a';if(!a[now][c])a[now][c]=++sz;now=a[now][c];
	}root[id]=now;
}
void AC(){
	for(i=0;i<26;++i)a[0][i]=1;q[0]=1;t=0;w=1;
	while(t!=w){
		int x=q[t++];
		for(int i=0;i<26;++i)if(a[x][i]){
			nxt[a[x][i]]=a[nxt[x]][i];q[w++]=a[x][i];
		}else a[x][i]=a[nxt[x]][i];
	}
}
void dfs(int x){L[x]=++ind;for(int i=g2.head[x];i;i=e[i].next)dfs(e[i].to);R[x]=ind;}
void dfs1(int x,int p){
	A(L[p],1);
	for(int i=0, y; i<v[x].size(); i++)y=v[x][i], ans[y]=Q(R[root[y]])-Q(L[root[y]]-1);
	for(int i=g1.head[x];i;i=e[i].next)dfs1(e[i].to,a[p][e[i].v-'a']);
	A(L[p],-1);
}
int main(){
	for(scanf("%d",&n),i=1;i<=n;++i){
		scanf("%d",&op);
		if(op==1)scanf(" %c",&ch),g1.ins(n+1,i,ch);else scanf("%d %c",&j,&ch),g1.ins(j,i,ch);
	}
	for(scanf("%d",&m),i=1;i<=m;++i)scanf("%d%s",&j,s),v[j].push_back(i),ins(i);AC();
	for(i=2;i<=sz;++i)g2.ins(nxt[i],i);dfs(1);
	for(dfs1(n+1,1),i=1;i<=m;++i)printf("%d\n",ans[i]);
}


#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#define N 400005
using namespace std;
struct pl{int fail,son[27];}s[N],e[N];
struct str{int v,nex;}l[N*2];
int n,cnt=1,cnt2=1,cnt3,x,y,m,len,tot;
struct ti{int id,pos;};
vector<ti>h[N];
int pos[N],dy[N],head[N],tree[N],fi[N],la[N],ans[N];char c,t[N];
queue<int>q;
void add(int a,int b){
	cnt3++;l[cnt3].v=b;l[cnt3].nex=head[a];head[a]=cnt3;
}
void dfs(int a,int fa){
	int i=head[a];fi[a]=++tot;
	while(i!=0){
		if(l[i].v!=fa) dfs(l[i].v,a);
		i=l[i].nex;
	}
	la[a]=tot;
}
void adt(int a,int b){
	while(a<=tot){
		tree[a]+=b;a+=a&-a;
	}
}
int find(int a){
	int an=0;
	while(a>0){
		an+=tree[a];a-=a&-a;
	}
	return an;
}
void dfs2(int a,int v){
	if(v==0) v=1;
	adt(fi[v],1);
	for(int i=0;i<h[a].size();i++){
		ti tmp=h[a][i];
		ans[tmp.id]=find(la[tmp.pos])-find(fi[tmp.pos]-1);
	}
	for(int i=1;i<=26;i++){
		if(s[a].son[i]==0) continue;
		dfs2(s[a].son[i],e[v].son[i]);
	}
	add(fi[v],-1);
}
int main()
{
	pos[0]=1;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&x);
		if(x==1){
			scanf(" %c",&c);
			int tmp=c-'a'+1;
			if(s[1].son[tmp]==0) s[1].son[tmp]=++cnt;
			pos[i]=s[1].son[tmp];
		}
		else{
			scanf("%d",&y);scanf(" %c",&c);int tmp=c-'a'+1;
			if(s[pos[y]].son[tmp]==0) s[pos[y]].son[tmp]=++cnt;
			pos[i]=s[pos[y]].son[tmp];
		}
	}
	scanf("%d",&m);
	for(int i=1;i<=m;i++){
		scanf("%d",&x);
		ti tmp;tmp.id=i;
		scanf("%s",t+1);len=strlen(t+1);
		int tp=1;
		for(int j=1;j<=len;j++){
			int tip=t[j]-'a'+1;
			if(e[tp].son[tip]==0) e[tp].son[tip]=++cnt2;
			tp=e[tp].son[tip];
		}
		tmp.pos=tp;h[pos[x]].push_back(tmp);
	}
	q.push(1);e[1].fail=1;
	while(!q.empty()){
		int tmp=q.front();q.pop();
		if(tmp==1){
			for(int j=1;j<=26;j++){
				if(e[1].son[j]==0) continue;
				e[e[1].son[j]].fail=1;q.push(e[1].son[j]);
			}
		}
		else{
			for(int j=1;j<=26;j++){
				if(e[tmp].son[j]==0){
					e[tmp].son[j]=e[e[tmp].fail].son[j];
				}
				else{
					e[e[tmp].son[j]].fail=e[e[tmp].fail].son[j];
					if(e[e[tmp].son[j]].fail==0) e[e[tmp].son[j]].fail=1;
					q.push(e[tmp].son[j]);
				}
			}
		}
	}
	for(int i=2;i<=cnt2;i++){
		add(i,e[i].fail);add(e[i].fail,i);
	}
	dfs(1,0);dfs2(1,1);
	for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
	return 0;
}


#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#define N 400005
using namespace std;
struct pl{int fail,son[27];}e[N];
struct str{int v,nex,w;}l[N*2],s[N*2];
int n,cnt=1,cnt2=1,cnt3,x,y,m,len,tot,cnt4;
struct ti{int id,pos;};
vector<ti>h[N];
int pos[N],dy[N],head[N],tree[N],fi[N],la[N],ans[N],he[N];char c,t[N];
queue<int>q;
void add(int a,int b){
	cnt3++;l[cnt3].v=b;l[cnt3].nex=head[a];head[a]=cnt3;
}
void dfs(int a,int fa){
	//cout<<a<<" <- "<<fa<<endl;
	int i=head[a];fi[a]=++tot;
	while(i!=0){
		if(l[i].v!=fa) dfs(l[i].v,a);a
		i=l[i].nex;
	}
	la[a]=tot;
}
void adt(int a,int b){
	while(a<=tot){
		tree[a]+=b;a+=a&-a;
	}
}
int find(int a){
	int an=0;
	while(a>0){
		an+=tree[a];a-=a&-a;
	}
	return an;
}
void dfs2(int a,int v){
	if(v==0) v=1;
	adt(fi[v],1);
	for(int i=0;i<h[a].size();i++){
		ti tmp=h[a][i];//cout<<"find:"<<a<<" "<<tmp.pos<<endl;
		ans[tmp.id]=find(la[tmp.pos])-find(fi[tmp.pos]-1);
	}
	int i=he[a];
	while(i!=0){
		dfs2(s[i].v,e[v].son[s[i].w]);
		i=s[i].nex;
	}
	adt(fi[v],-1);
}
void add2(int a,int b,int c){
	cnt4++;s[cnt4].v=b;s[cnt4].nex=he[a];he[a]=cnt4;s[cnt4].w=c;
}
int main()
{
	pos[0]=1;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&x);
		if(x==1){
			scanf(" %c",&c);
			int tmp=c-'a'+1;
			cnt++;add2(1,cnt,tmp);
			pos[i]=cnt;
		}
		else{
			scanf("%d",&y);scanf(" %c",&c);int tmp=c-'a'+1;
			cnt++;add2(pos[y],cnt,tmp);
			pos[i]=cnt;
		}
	}
	scanf("%d",&m);
	for(int i=1;i<=m;i++){
		scanf("%d",&x);
		ti tmp;tmp.id=i;
		scanf("%s",t+1);len=strlen(t+1);
		int tp=1;
		for(int j=1;j<=len;j++){
			int tip=t[j]-'a'+1;
			if(e[tp].son[tip]==0) e[tp].son[tip]=++cnt2;
			tp=e[tp].son[tip];
		}
		tmp.pos=tp;h[pos[x]].push_back(tmp);
	}
	q.push(1);e[1].fail=1;
	while(!q.empty()){
		int tmp=q.front();q.pop();
		if(tmp==1){
			for(int j=1;j<=26;j++){
				if(e[1].son[j]==0) {e[1].son[j]=1;continue;}
				e[e[1].son[j]].fail=1;q.push(e[1].son[j]);
			}
		}
		else{
			for(int j=1;j<=26;j++){
				if(e[tmp].son[j]==0){
					e[tmp].son[j]=e[e[tmp].fail].son[j];
				}
				else{
					e[e[tmp].son[j]].fail=e[e[tmp].fail].son[j];
					if(e[e[tmp].son[j]].fail==0) e[e[tmp].son[j]].fail=1;
					q.push(e[tmp].son[j]);
				}
			}
		}
	}
	for(int i=2;i<=cnt2;i++){
		add(i,e[i].fail);add(e[i].fail,i);
	}
	dfs(1,0);dfs2(1,1);
	for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
	return 0;
}
/*
8
1 a
2 1 a
2 2 a
2 3 a
2 1 a
2 5 b
2 6 c
2 7 d
5
4 a
4 b
8 a
8 ab
8 aabcd
*/


#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#define N 400005
using namespace std;
struct pl{int fail,son[27];}e[N];
struct str{int v,nex,w;}l[N*2],s[N*2];
int n,cnt=1,cnt2=1,cnt3,x,y,m,len,tot,cnt4;
struct ti{int id,pos;};
vector<ti>h[N];
int pos[N],dy[N],head[N],tree[N],fi[N],la[N],ans[N],he[N];char c,t[N];
queue<int>q;
void add(int a,int b){
	cnt3++;l[cnt3].v=b;l[cnt3].nex=head[a];head[a]=cnt3;
}
void dfs(int a,int fa){
	//cout<<a<<" <- "<<fa<<endl;
	int i=head[a];fi[a]=++tot;
	while(i!=0){
		if(l[i].v!=fa) dfs(l[i].v,a);
		i=l[i].nex;
	}
	la[a]=tot;
}
void adt(int a,int b){
	while(a<=tot){
		tree[a]+=b;a+=a&-a;
	}
}
int find(int a){
	int an=0;
	while(a>0){
		an+=tree[a];a-=a&-a;
	}
	return an;
}
void dfs2(int a,int v){
	if(v==0) v=1;
	adt(fi[v],1);
	for(int i=0;i<h[a].size();i++){
		ti tmp=h[a][i];//cout<<"find:"<<a<<" "<<tmp.pos<<endl;
		ans[tmp.id]=find(la[tmp.pos])-find(fi[tmp.pos]-1);
	}
	int i=he[a];
	while(i!=0){
		dfs2(s[i].v,e[v].son[s[i].w]);
		i=s[i].nex;
	}
	adt(fi[v],-1);
}
void add2(int a,int b,int c){
	cnt4++;s[cnt4].v=b;s[cnt4].nex=he[a];he[a]=cnt4;s[cnt4].w=c;
}
int main()
{
	pos[0]=1;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&x);
		if(x==1){
			scanf(" %c",&c);
			int tmp=c-'a'+1;
			cnt++;add2(1,cnt,tmp);
			pos[i]=cnt;
		}
		else{
			scanf("%d",&y);scanf(" %c",&c);int tmp=c-'a'+1;
			cnt++;add2(pos[y],cnt,tmp);
			pos[i]=cnt;
		}
	}
	scanf("%d",&m);
	for(int i=1;i<=m;i++){
		scanf("%d",&x);
		ti tmp;tmp.id=i;
		scanf("%s",t+1);len=strlen(t+1);
		int tp=1;
		for(int j=1;j<=len;j++){
			int tip=t[j]-'a'+1;
			if(e[tp].son[tip]==0) e[tp].son[tip]=++cnt2;
			tp=e[tp].son[tip];
		}
		tmp.pos=tp;h[pos[x]].push_back(tmp);
	}
	q.push(1);e[1].fail=1;
	while(!q.empty()){
		int tmp=q.front();q.pop();
		if(tmp==1){
			for(int j=1;j<=26;j++){
				if(e[1].son[j]==0) {e[1].son[j]=1;continue;}
				e[e[1].son[j]].fail=1;q.push(e[1].son[j]);
			}
		}
		else{
			for(int j=1;j<=26;j++){
				if(e[tmp].son[j]==0){
					e[tmp].son[j]=e[e[tmp].fail].son[j];
				}
				else{
					e[e[tmp].son[j]].fail=e[e[tmp].fail].son[j];
					if(e[e[tmp].son[j]].fail==0) e[e[tmp].son[j]].fail=1;
					q.push(e[tmp].son[j]);
				}
			}
		}
	}
	for(int i=2;i<=cnt2;i++){
		add(i,e[i].fail);add(e[i].fail,i);
	}
	dfs(1,0);dfs2(1,1);
	for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
	return 0;
}
/*
8
1 a
2 1 a
2 2 a
2 3 a
2 1 a
2 5 b
2 6 c
2 7 d
5
4 a
4 b
8 a
8 ab
8 aabcd
*/


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

const int var = 26;	// the number of charactor types

int trans(char c) {
	return c - 'a';
}

class aho_corasick {
	struct ac_node {
		int fail;
		int next[var];
		vector<int> ok;
		ac_node() : fail(-1) {
			memset(next, -1, sizeof(int) * var);
		}
	};
	vector<int> unite(const vector<int>& a, const vector<int>& b) {
		vector<int> res;
		set_union(a.begin(), a.end(), b.begin(), b.end(), back_inserter(res));
		return move(res);
	}
	int n;
public:
	vector<ac_node> dat;
	aho_corasick(const vector<string>& Ts) : n(Ts.size()), dat(1) {
		int now;
		dat[0].fail = 0;
		for (int i = 0; i < n; i++) {
			auto &T = Ts[i];
			now = 0;
			for (auto c : T) {
				if (dat[now].next[trans(c)] == -1) {
					dat[now].next[trans(c)] = dat.size();
					dat.emplace_back();
				}
				now = dat[now].next[trans(c)];
			}
			dat[now].ok.push_back(i);
		}
		queue<int> q;
		for (int i = 0; i < var; i++) {
			if (dat[0].next[i] == -1) {
				dat[0].next[i] = 0;
			}
			else {
				dat[dat[0].next[i]].fail = 0;
				q.push(dat[0].next[i]);
			}
		}
		while (!q.empty()) {
			now = q.front(); q.pop();
			for (int i = 0; i < var; i++) {
				if (dat[now].next[i] != -1) {
					int nx = dat[now].fail;
					while (dat[nx].next[i] == -1) {
						nx = dat[nx].fail;
					}
					int nex = dat[now].next[i];
					dat[nex].fail = dat[nx].next[i];
					dat[nex].ok = unite(dat[nex].ok, dat[dat[nx].next[i]].ok);
					q.push(nex);
				}
			}
		}
	}
	int size() const {
		return dat.size();
	}
	bool is_ok(int id) const {
		return !dat[id].ok.empty();
	}
	int get_next(int id, char c) {
		vector<int> pos;
		while (dat[id].next[trans(c)] == -1) {
			pos.push_back(id);
			id = dat[id].fail;
		}
		for (auto p : pos) dat[p].next[trans(c)] = dat[id].next[trans(c)];
		return dat[id].next[trans(c)];
	}
};

const int MAX = 4e5;

int cnt[MAX];
int res[MAX];

vector<pair<int, int>> G[MAX + 1];
vector<pair<int, int>> qs[MAX + 1];

void dfs(int v, int id, aho_corasick& ac) {
	for (const auto& p : qs[v]) {
		res[p.first] = cnt[p.second];
	}
	for (const auto& e : G[v]) {
		int to = ac.get_next(id, e.second);
		for (auto k : ac.dat[to].ok) ++cnt[k];
		dfs(e.first, to, ac);
		for (auto k : ac.dat[to].ok) --cnt[k];
	}
}

const int rh_mod = 1e9 + 7;
const int rh_b1 = 1009, rh_b2 = 10007;

ll rolling_hash(const string& s) {
	ll h1 = 0, h2 = 0;
	for (auto c : s) {
		h1 = (1LL * h1 * rh_b1 + c) % rh_mod;
		h2 = (1LL * h2 * rh_b2 + c) % rh_mod;
	}
	return (h1 << 32LL) | h2;
}

int main()
{
	ios::sync_with_stdio(false), cin.tie(0);
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++) {
		int com;
		cin >> com;
		if (com == 1) {
			char c;
			cin >> c;
			G[0].emplace_back(i, c);
		}
		else {
			int j;
			char c;
			cin >> j >> c;
			G[j].emplace_back(i, c);
		}
	}
	int m;
	cin >> m;
	vector<string> ts;
	unordered_map<ll, int> dic;
	for (int i = 0; i < m; i++) {
		int id;
		string t;
		cin >> id >> t;
		ll hs = rolling_hash(t);
		if (!dic.count(hs)) {
			dic[hs] = ts.size();
			ts.emplace_back(t);
		}
		qs[id].emplace_back(i, dic[hs]);
	}
	aho_corasick ac(ts);
	dfs(0, 0, ac);
	for (int i = 0; i < m; i++) {
		printf("%d\n", res[i]);
	}
	return 0;
}


#include<bits/stdc++.h>
#define ll long long
#define mk make_pair
#define ft first
#define se second
#define pii pair<int,int>
#define db double
#define ls o<<1
#define rs o<<1|1
using namespace std;
const int M=4e5+5;
char s[M];
struct AC_Automaton{
    int go[M][26],fail[M],root,sz;
    vector<pii>q[M],tr[M];
    int res[M];
    vector<int>G[M];
    int L[M],R[M],dfn;

    void init(){
        dfn=sz=0;
        root=sz++;
    }

    int add(){
        int cur=root;
        for(int i=0;s[i];i++){
            int x=s[i]-'a';
            if(!go[cur][x]){
                go[cur][x]=sz++;
            }
            cur=go[cur][x];
        }
        return cur;
    }
    void getfail(){
        queue<int>Q;
        int cur=root;
        for(int i=0;i<26;i++){
            if(go[cur][i]){
                fail[go[cur][i]]=root;
                Q.push(go[cur][i]);
            }
        }
        while(!Q.empty()){
            int u=Q.front();Q.pop();

            G[fail[u]].push_back(u);

            for(int i=0;i<26;i++){
                if(go[u][i]){
                    fail[go[u][i]]=go[fail[u]][i];
                    Q.push(go[u][i]);
                }else
                    go[u][i]=go[fail[u]][i];
            }
        }
    }
    int V[M<<2];
    void upd(int o,int l,int r,int p,int x){
        V[o]+=x;
        if(l==r)return;
        int mid=(l+r)/2;
        if(p<=mid)
            upd(ls,l,mid,p,x);
        else
            upd(rs,mid+1,r,p,x);
    }
    int qy(int o,int l,int r,int L,int R){
        if(L<=l&&r<=R)
            return V[o];
        int mid=(l+r)/2;
        int ans=0;
        if(L<=mid)
            ans+=qy(ls,l,mid,L,R);
        if(R>mid)
            ans+=qy(rs,mid+1,r,L,R);
        return ans;
    }
    void dfs(int u){
        L[u]=++dfn;
        for(auto v:G[u])
            dfs(v);
        R[u]=dfn;
    }
    void dfs2(int x,int u){
        upd(1,1,dfn,L[u],1);
        for(auto tp:q[x])
            res[tp.se]=qy(1,1,dfn,L[tp.ft],R[tp.ft]);
        for(auto tp:tr[x])
            dfs2(tp.se,go[u][tp.ft]);
        upd(1,1,dfn,L[u],-1);
    }
    void gao(){
        init();
        int n;scanf("%d",&n);
        for(int i=1;i<=n;i++){
            int op;
            scanf("%d",&op);
            if(op==1){
                scanf("%s",s);
                tr[0].push_back({s[0]-'a',i});
            }else{
                int x;
                scanf("%d%s",&x,s);
                tr[x].push_back({s[0]-'a',i});
            }
        }
        int m;scanf("%d",&m);
        for(int i=1;i<=m;i++){
            int x;
            scanf("%d%s",&x,s);
            q[x].push_back({add(),i});
        }

        getfail();
        dfs(root);
        dfs2(0,root);
        for(int i=1;i<=m;i++)
            printf("%d\n",res[i]);
    }
}ac;
int main(){
    ac.gao();
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int Alpha=28;
vector<int> G[1000000];
int tim=2;
int L[2000000];
int R[2000000];
int node[2000000];
class SuffixAutomata{
    public:
    struct state {
        int len, link;
        int next[Alpha];
        state(){
            len = link = 0;
            memset(next , -1 , sizeof(next));
        }
    };
    int sz=1, last=0;
    vector<state> st;
    vector<int> terminal;
    void Init(int len) {
        st.clear();
        terminal.clear();
        st.resize(2*len);
        terminal.resize(2*len);
        sz = 1;
        st[0].len = 0;
        st[0].link = -1;
    }
    int extend(char ccc,int last) {
        int c = ccc - 'a';
        if (st[last].next[c]!=-1){
            last = st[last].next[c];
            return last;
        }
        int cur = sz++;
        st[cur].len = st[last].len + 1;
        int p = last;
        while (p != -1 && st[p].next[c] == -1) {
            st[p].next[c] = cur;
            p = st[p].link;
        }
        if (p == -1) {
            st[cur].link = 0;
        }
        else {
            int q = st[p].next[c];
            if (st[p].len + 1 == st[q].len) {
                st[cur].link = q;
            } else {
                int clone = sz++;
                st[clone].len = st[p].len + 1;
                for(int j = 0 ; j < Alpha ; j++)
                    st[clone].next[j] = st[q].next[j];
                st[clone].link = st[q].link;
                while (p != -1 && st[p].next[c] == q) {
                    st[p].next[c] = clone;
                    p = st[p].link;
                }
                st[q].link = st[cur].link = clone;
            }
        }
        return cur;
    }
    void getTerminal()
    {
        int p=last;
        while(p>0)terminal[p]=1,p=st[p].link;
    }
    void build(string s)
    {
        Init(s.size());
        for (auto x:s)extend(x,last);
        getTerminal();
    }
    void dfs(int v) {
        node[v] = tim;
        L[v] = tim++;
        for (auto u:G[v]) {
            dfs(u);
        }
        R[v] = tim-1;
    }
    void solve() {
        for (int i=0;i<sz;i++) {
            if (st[i].link!=-1)G[st[i].link].push_back(i);
        }
        dfs(0);
    }
    int getNode(string s) {
        int v=0;
        for (auto x:s) {
            v = st[v].next[x-'a'];
            if (v==-1)return v;
        }
        return v;
    }
};

char a[1000000];
vector<int> adj[1000000];
SuffixAutomata SA;
int cnt[1000000];
vector<int> Q[1000000];
string t[1000000];
int ret[1000000];
int BIT[3000000];
void update(int x, int delta)
{
    for(; x <= tim; x += x&-x)
        BIT[x] += delta;
}
int query(int x)
{
    int sum = 0;
    for(; x > 0; x -= x&-x)
        sum += BIT[x];
    return sum;
}
void pre(int v,int cur) {
    int nLast = 0;
    if (v!=0) {
        nLast = SA.extend(a[v],cur);
    }
    for (auto u:adj[v]) {
        pre(u,nLast);
    }
}
char inp[1000000];
void solve(int v=0,int V=0) {
    if (v)V = SA.st[V].next[a[v]-'a'];
    if(V>0)update(node[V],1);
    for (auto q:Q[v]) {
        int need = SA.getNode(t[q]);
        ret[q] = query(R[need]) - query(L[need]-1);
    }
    for (auto u:adj[v]) {
        solve(u,V);
    }
    if (V>0)update(node[V],-1);
}
int main()
{
    int n;
    scanf("%d",&n);
    for (int i=1;i<=n;i++){
        int typ,par;
        char c=' ';
        scanf("%d",&typ);
        par = 0;
        if (typ==1) {
            while(c==' ')scanf("%c",&c);
        } else {
            scanf("%d",&par);
            while(c==' ')scanf("%c",&c);
        }
        adj[par].push_back(i);
        a[i] = c;

    }
    int q;
    scanf("%d",&q);
    for (int i=0;i<q;i++){
        int v;
        scanf("%d",&v);
        scanf("%s",inp);t[i]=inp;
        Q[v].push_back(i);
    }
    SA.Init(1e6);
    pre(0,0);
    SA.solve();
    solve(0,0);
    for (int i=0;i<q;i++) {
        printf("%d\n",ret[i]);
    }
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int Alpha=28;
vector<int> G[1000000];
int tim=2;
int L[2000000];
int R[2000000];
int node[2000000];
class SuffixAutomata{
    public:
    struct state {
        int len, link;
        int next[Alpha];
        state(){
            len = link = 0;
            memset(next , -1 , sizeof(next));
        }
    };
    int sz=1, last=0;
    vector<state> st;
    vector<int> terminal;
    void Init(int len) {
        st.clear();
        terminal.clear();
        st.resize(2*len);
        terminal.resize(2*len);
        sz = 1;
        st[0].len = 0;
        st[0].link = -1;
    }
    int extend(char ccc,int last) {
        int c = ccc - 'a';
        /*if (st[last].next[c]!=-1){
            last = st[last].next[c];
            return last;
        }*/
        int cur = sz++;
        st[cur].len = st[last].len + 1;
        int p = last;
        while (p != -1 && st[p].next[c] == -1) {
            st[p].next[c] = cur;
            p = st[p].link;
        }
        if (p == -1) {
            st[cur].link = 0;
        }
        else {
            int q = st[p].next[c];
            if (st[p].len + 1 == st[q].len) {
                st[cur].link = q;
            } else {
                int clone = sz++;
                st[clone].len = st[p].len + 1;
                for(int j = 0 ; j < Alpha ; j++)
                    st[clone].next[j] = st[q].next[j];
                st[clone].link = st[q].link;
                while (p != -1 && st[p].next[c] == q) {
                    st[p].next[c] = clone;
                    p = st[p].link;
                }
                st[q].link = st[cur].link = clone;
            }
        }
        return cur;
    }
    void getTerminal()
    {
        int p=last;
        while(p>0)terminal[p]=1,p=st[p].link;
    }
    void build(string s)
    {
        Init(s.size());
        for (auto x:s)extend(x,last);
        getTerminal();
    }
    void dfs(int v) {
        node[v] = tim;
        L[v] = tim++;
        for (auto u:G[v]) {
            dfs(u);
        }
        R[v] = tim-1;
    }
    void solve() {
        for (int i=0;i<sz;i++) {
            if (st[i].link!=-1)G[st[i].link].push_back(i);
        }
        dfs(0);
    }
    int getNode(string s) {
        int v=0;
        for (auto x:s) {
            v = st[v].next[x-'a'];
            if (v==-1)return v;
        }
        return v;
    }
};

char a[1000000];
vector<int> adj[1000000];
SuffixAutomata SA;
int cnt[1000000];
vector<int> Q[1000000];
string t[1000000];
int ret[1000000];
int BIT[3000000];
void update(int x, int delta)
{
    for(; x <= tim; x += x&-x)
        BIT[x] += delta;
}
int query(int x)
{
    int sum = 0;
    for(; x > 0; x -= x&-x)
        sum += BIT[x];
    return sum;
}
void pre(int v,int cur) {
    int nLast = 0;
    if (v!=0) {
        nLast = SA.extend(a[v],cur);
    }
    for (auto u:adj[v]) {
        pre(u,nLast);
    }
}
char inp[1000000];
void solve(int v=0,int V=0) {
    if (v)V = SA.st[V].next[a[v]-'a'];
    if(V>0)update(node[V],1);
    for (auto q:Q[v]) {
        int need = SA.getNode(t[q]);
        ret[q] = query(R[need]) - query(L[need]-1);
    }
    for (auto u:adj[v]) {
        solve(u,V);
    }
    if (V>0)update(node[V],-1);
}
int main()
{
    int n;
    scanf("%d",&n);
    for (int i=1;i<=n;i++){
        int typ,par;
        char c=' ';
        scanf("%d",&typ);
        par = 0;
        if (typ==1) {
            while(c==' ')scanf("%c",&c);
        } else {
            scanf("%d",&par);
            while(c==' ')scanf("%c",&c);
        }
        adj[par].push_back(i);
        a[i] = c;

    }
    int q;
    scanf("%d",&q);
    for (int i=0;i<q;i++){
        int v;
        scanf("%d",&v);
        scanf("%s",inp);t[i]=inp;
        Q[v].push_back(i);
    }
    SA.Init(1e6);
    pre(0,0);
    SA.solve();
    solve(0,0);
    for (int i=0;i<q;i++) {
        printf("%d\n",ret[i]);
    }
}