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

#define pb push_back
#define CLR(x,y) memset(x,y,sizeof(x))
#define SQ(x) ((x)*(x))
#define ALL(x) (x).begin(),(x).end()
#define LL long long

const int Size = 205055;

/// typ = 1 = insert
/// typ = 2 = query
/// typ = 3 = delete

struct PRR{
    int strIdx;
    int typ;
    int U;
    int V;
    int Tm;
    int idx;
    PRR(){
    }
    PRR(int _strIdx,int _typ,int _U,int _V,int _Tm){
        strIdx = _strIdx;
        typ = _typ;
        U = _U;
        V = _V;
        Tm = _Tm;
    }
};

bool cmp(PRR a,PRR b){
    if(a.Tm == b.Tm){
        return (a.typ < b.typ);
    }
    return (a.Tm<b.Tm);
}

int N,Q;
vector<PRR> List;
int typ,U,V,Tm;

LL DP[55][55];
LL RES[Size];
char SS[100005][55];

struct node {
    LL cnt;
    int child[27];
    node(){
    }
};

LL NC2(LL N){
    if(N<=1) return 0;
    return N*(N-1)/2LL;
}

struct trie {
    void clear_new_node() {
        node newNode;
        tree.pb(newNode);
        tree[node_ID].cnt = 0;
        CLR(tree[node_ID].child, -1);
        node_ID++;
    }

    vector<node> tree;
    int node_ID;
    void initialize() {
        node_ID = 0;
        clear_new_node();
    }

    void insert_word(int idx, int pos, int Len) {
        int cur = 0;
        for (int i = pos; i < Len; ++i) {
            int id = SS[idx][i] - 'a';
            if (tree[cur].child[id] == -1) {
                tree[cur].child[id] = node_ID;
                clear_new_node();
            }
            cur = tree[cur].child[id];
            LL prev = DP[pos][i];
            DP[pos][i] -= NC2(tree[cur].cnt);
            tree[cur].cnt++;
            DP[pos][i] += NC2(tree[cur].cnt);
        }
    }

    void delete_word(int idx, int pos, int Len) {
        int cur = 0;
        for (int i = pos; i < Len; ++i) {
            int id = SS[idx][i] - 'a';
            if (tree[cur].child[id] == -1) {
                return;
            }
            cur = tree[cur].child[id];
            DP[pos][i] -= NC2(tree[cur].cnt);
            tree[cur].cnt--;
            DP[pos][i] += NC2(tree[cur].cnt);
        }
    }
};

trie root[55];

void solve(){
    for(int i = 0;i<55;i++) root[i].initialize();
    sort(ALL(List),cmp);
    CLR(DP,0);

    for(int i = 0;i<List.size();i++){
        PRR cur = List[i];
        if(cur.typ == 2){ /// Query:
            RES[cur.idx] = DP[cur.U][cur.V];
        }else if(cur.typ == 1){ /// Insert:
            int Len = strlen(SS[cur.strIdx]);
            for(int p = 0;p<Len;p++){
                root[p].insert_word(cur.strIdx,p,Len);
            }
        }else{ /// Delete:
            int Len = strlen(SS[cur.strIdx]);
            for(int p = 0;p<Len;p++){
                root[p].delete_word(cur.strIdx,p,Len);
            }
        }
    }

    for(int i = 0;i<Q;i++){
        printf("%lld\n",RES[i]);
    }
}

int main () {

    scanf("%d",&N);
    PRR P;
    for(int i = 0;i<N;i++){
        scanf("%s %d %d",SS[i],&U,&V);
        P.strIdx = i; P.typ = 1; P.Tm = U;
        List.pb(P);
        P.strIdx = i; P.typ = 3; P.Tm = V;
        List.pb(P);
    }

    scanf("%d",&Q);
    for(int i = 0;i<Q;i++){
        scanf("%d %d %d",&U,&V,&Tm);
        U--;V--;
        P.U = U; P.V = V; P.Tm = Tm ;P.typ = 2; P.idx = i;
        List.pb(P);
    }
    solve();
    return 0;
}
