#include <bits/stdc++.h>
template <class T>
T max(T x, T y) {
  return x > y ? x : y;
}
template <class T>
T min(T x, T y) {
  return x < y ? x : y;
}
long long read() {
  long long s = 0, w = 1;
  char ch = getchar();
  while (ch < '0' || ch > '9') {
    if (ch == '-') w = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9')
    s = (s << 3) + (s << 1) + (ch ^ 48), ch = getchar();
  return s * w;
}
struct Edge {
  long long to, next;
} e[100010];
struct Ask {
  long long l, r, k, rk, o;
} q[100010];
long long n, m, cnt, tot, num, sz;
long long fail[100010], son[100010][26], lth[100010], head[100010], a[100010];
long long sum[100010], pre[100010], pr[100010];
long long rt[100010], ls[100010 << 6], rs[100010 << 6], d[100010 << 6];
std::string S[100010];
char T[100010];
std::vector<long long> v[100010];
long long cmp(Ask x, Ask y) { return x.o == y.o ? x.k < y.k : x.o > y.o; }
void add(long long x, long long y) {
  e[++num] = (Edge){y, head[x]}, head[x] = num;
}
void Do() {
  for (long long i = 1; i <= n; i++) pre[i] = pre[i - 1] + sum[a[i]];
}
void Ins(long long i) {
  scanf("%s", T), S[i] = T;
  lth[i] = S[i].size(), tot += lth[i];
  long long now = 0;
  for (long long j = 0; j < S[i].size(); j++) {
    if (!son[now][S[i][j] - 'a']) son[now][S[i][j] - 'a'] = ++cnt;
    now = son[now][S[i][j] - 'a'];
  }
  v[now].push_back(i);
  a[i] = now;
}
void Build() {
  std::queue<long long> q;
  for (long long i = 0; i < 26; i++)
    if (son[0][i]) q.push(son[0][i]);
  while (!q.empty()) {
    long long k = q.front();
    q.pop();
    for (long long i = 0; i < 26; i++)
      if (son[k][i])
        fail[son[k][i]] = son[fail[k]][i], q.push(son[k][i]);
      else
        son[k][i] = son[fail[k]][i];
  }
}
long long change(long long k, long long x, long long y, long long pos) {
  long long rt = ++sz;
  d[rt] = d[k] + 1;
  if (x == y) return rt;
  ls[rt] = ls[k], rs[rt] = rs[k];
  long long mid = x + y >> 1;
  if (pos <= mid)
    ls[rt] = change(ls[k], x, mid, pos);
  else
    rs[rt] = change(rs[k], mid + 1, y, pos);
  return rt;
}
long long query(long long p, long long x, long long y, long long pos) {
  if (!pos) return 0;
  if (x == y) return d[p];
  long long mid = x + y >> 1;
  if (pos <= mid) return query(ls[p], x, mid, pos);
  return d[ls[p]] + query(rs[p], mid + 1, y, pos);
}
void Query(long long i) {
  long long now = 0;
  for (long long j = 0; j < lth[i]; j++)
    now = son[now][S[i][j] - 'a'], sum[now]++;
}
void dfs(long long x) {
  for (long long i = head[x]; i; i = e[i].next)
    dfs(e[i].to), sum[x] += sum[e[i].to];
}
void Dfs(long long x) {
  for (long long i = head[x]; i; i = e[i].next) {
    rt[e[i].to] = rt[x];
    for (long long j = 0; j < v[e[i].to].size(); j++)
      rt[e[i].to] = change(rt[e[i].to], 1, n, v[e[i].to][j]);
    Dfs(e[i].to);
  }
}
signed main() {
  n = read(), m = read();
  for (long long i = 1; i <= n; i++) Ins(i);
  tot = sqrt(tot), Build();
  for (long long i = 1; i <= m; i++)
    q[i].l = read(), q[i].r = read(), q[i].k = read(), q[i].rk = i,
    q[i].o = (lth[q[i].k] > tot);
  std::sort(q + 1, q + m + 1, cmp);
  for (long long i = 1; i <= cnt; i++) add(fail[i], i);
  Dfs(0);
  long long L = 1, R = 1;
  Query(q[1].k), dfs(0), Do();
  for (long long i = 2; i <= m + 1; i++) {
    if (lth[q[i].k] <= tot) {
      for (long long j = L; j < i; j++)
        pr[q[j].rk] = pre[q[j].r] - pre[q[j].l - 1];
      R = i;
      break;
    }
    if (q[i].k != q[i - 1].k) {
      for (long long j = L; j < i; j++)
        pr[q[j].rk] = pre[q[j].r] - pre[q[j].l - 1];
      memset(sum, 0, sizeof(sum)), Query(q[i].k), dfs(0), Do(), L = i;
    }
  }
  for (long long i = R; i <= m; i++) {
    long long now = 0;
    for (long long j = 0; j < lth[q[i].k]; j++)
      now = son[now][S[q[i].k][j] - 'a'],
      pr[q[i].rk] +=
          query(rt[now], 1, n, q[i].r) - query(rt[now], 1, n, q[i].l - 1);
  }
  for (long long i = 1; i <= m; i++) printf("%lld\n", pr[i]);
  return 0;
}
