#include <iostream>
#include <algorithm>
#include <utility>
#include <vector>
#include <numeric>
#include <string>
#include <tuple>

template <class T, class U>
inline bool chmin(T& lhs, const U& rhs) {
  if (lhs > rhs) {
    lhs = rhs;
    return true;
  }
  return false;
}

template <class T, class U>
inline bool chmax(T& lhs, const U& rhs) {
  if (lhs < rhs) {
    lhs = rhs;
    return true;
  }
  return false;
}

// [l, r) from l to r
struct range {
  struct itr {
    int i;
    constexpr itr(int i_): i(i_) { }
    constexpr void operator ++ () { ++i; }
    constexpr int operator * () const { return i; }
    constexpr bool operator != (itr x) const { return i != x.i; }
  };
  const itr l, r;
  constexpr range(int l_, int r_): l(std::min<int>(l_, r_)), r(r_) {}
  constexpr itr begin() const { return l; }
  constexpr itr end() const { return r; }
};

// [l, r) from r to l
struct revrange {
  struct itr {
    int i;
    constexpr itr(int i_): i(i_) { }
    constexpr void operator ++ () { --i; }
    constexpr int operator * () const { return i; }
    constexpr bool operator != (itr x) const { return i != x.i; }
  };
  const itr r, l;
  constexpr revrange(int l_, int r_): r(std::max<int>(l_, r_) - 1), l(l_ - 1) {}
  constexpr itr begin() const { return r; }
  constexpr itr end() const { return l; }
};

template <class T>
inline T scan() {
  T res;
  std::cin >> res;
  return res;
}

template <int LETTER = 26>
class prefix_tree {
private:
  struct node {
    int index;
    int next[LETTER];
    int count;
    char letter;
    node(char c = 'a'): letter(c), index(-1), count(0) {
      std::fill(next, next + LETTER, -1);
    }
  };

  const char base;
  std::vector<node> data;

  int& next(int i, int j) {
    return data[i].next[j];
  }

public:
  prefix_tree(char base = 'a', char root = '$'): base(base) { data.emplace_back(root); }

  void add(const std::string& str, int index) {
    int pos = 0;
    for (int i = 0; i < str.size(); ++i) {
      int k = str[i] - base;
      if (next(pos, k) != -1) {
        pos = next(pos, k);
        continue;
      }
      int pos_new = data.size();
      next(pos, k) = pos_new;
      data.emplace_back(str[i]);
      pos = pos_new;
    }
    data[pos].index = index;
  }

  int find(const std::string& str) const {
    int pos = 0;
    for (int i = 0; i < str.size(); ++i) {
      int k = str[i] - base;
      if (next(pos, k) == -1) return -1;
      pos = next(pos, k);
    }
    return pos;
  }

  int find(int i, char c) {
    return next(i, c - base);
  }

  int index(int i) const {
    return i == -1 ? -1 : data[i].index;
  }

  int dfs(int v = 0) {
    if (index(v) != -1) {
      ++data[v].count;
    }
    for (int j = 0; j < LETTER; ++j) {
      if (next(v, j) != -1) {
        data[v].count += dfs(next(v, j));
      }
    }
    return data[v].count;
  }

  node info(int i, int j) {
    if (next(i, j) == -1) {
      return node();
    }
    else {
      return data[next(i, j)];
    }
  };

};

int main() {
  int N;
  std::cin >> N;
  std::vector<std::string> S(N);
  prefix_tree<26> trie;
  for (int i: range(0, N)) {
    std::cin >> S[i];
    trie.add(S[i], i);
  }
  trie.dfs();
  std::vector<int> always(N);
  std::vector<std::vector<std::vector<int>>> calc(N, std::vector<std::vector<int>>(26, std::vector<int>(26)));
  for (int i: range(0, N)) {
    int pos = 0;
    for (auto c: S[i]) {
      if (trie.info(pos, c - 'a').index != -1) {
        ++always[i];
      } 
      for (int j: range(0, 26)) {
        calc[i][j][c - 'a'] += trie.info(pos, j).count;
      }
      pos = trie.find(pos, c);
    }
  }
  int Q;
  std::cin >> Q;
  while (Q--) {
    int k;
    std::string p;
    std::cin >> k >> p;
    --k;
    std::vector<int> pos(26);
    for (int i: range(0, 26)) {
      pos[p[i] - 'a'] = i;
    }
    int ans = always[k];
    for (int i: range(0, 26)) {
      for (int j: range(0, 26)) {
        if (pos[i] < pos[j]) {
          ans += calc[k][i][j];
        }
      }
    }
    std::cout << ans << '\n';
  }
  return 0;
}


Measured memory_bytes: 369532