#include <bits/stdc++.h>
using namespace std;
const int MAXN = 400005;
template <typename T>
inline void read(T &AKNOI) {
  T x = 0, flag = 1;
  char ch = getchar();
  while (!isdigit(ch)) {
    if (ch == '-') flag = -1;
    ch = getchar();
  }
  while (isdigit(ch)) {
    x = x * 10 + ch - '0';
    ch = getchar();
  }
  AKNOI = flag * x;
}
int n, Q;
char s[MAXN];
struct SEG {
  int tot, root[MAXN], lc[MAXN * 25], rc[MAXN * 25];
  long long sum[MAXN * 25];
  void Insert(int &rt, int b, int e, int p) {
    if (!rt) rt = ++tot;
    ++sum[rt];
    if (b == e) return;
    int mid = (b + e) >> 1;
    if (p <= mid)
      Insert(lc[rt], b, mid, p);
    else
      Insert(rc[rt], mid + 1, e, p);
  }
  int Merge(int x, int y) {
    if (!x || !y) return x | y;
    int z = ++tot;
    sum[z] = sum[x] + sum[y];
    lc[z] = Merge(lc[x], lc[y]);
    rc[z] = Merge(rc[x], rc[y]);
    return z;
  }
  long long Query(int rt, int b, int e, int l, int r) {
    if (!rt) return 0;
    if (l <= b && e <= r) return sum[rt];
    int mid = (b + e) >> 1;
    if (r <= mid) return Query(lc[rt], b, mid, l, r);
    if (l > mid) return Query(rc[rt], mid + 1, e, l, r);
    return Query(lc[rt], b, mid, l, r) + Query(rc[rt], mid + 1, e, l, r);
  }
  inline void insert(int x, int p) { Insert(root[x], 1, n, p); }
  inline void merge(int x, int y) { root[x] = Merge(root[x], root[y]); }
  inline long long query(int x, int l, int r) {
    return Query(root[x], 1, n, l, r);
  }
} seg;
struct SAM {
  int tot, last, fa[MAXN], ch[MAXN][26], maxl[MAXN];
  int pos[MAXN], cnt[MAXN], seq[MAXN];
  void Extend(int x) {
    if (ch[last][x]) {
      int p = last, q = ch[p][x];
      if (maxl[q] == maxl[p] + 1) {
        last = q;
      } else {
        int nq = ++tot;
        maxl[last = nq] = maxl[p] + 1;
        memcpy(ch[nq], ch[q], sizeof(ch[nq]));
        fa[nq] = fa[q];
        fa[q] = nq;
        for (; p && ch[p][x] == q; p = fa[p]) {
          ch[p][x] = nq;
        }
      }
    } else {
      int p = last, np = ++tot;
      maxl[last = np] = maxl[p] + 1;
      for (; p && !ch[p][x]; p = fa[p]) {
        ch[p][x] = np;
      }
      if (!p) {
        fa[np] = 1;
      } else {
        int q = ch[p][x];
        if (maxl[q] == maxl[p] + 1) {
          fa[np] = q;
        } else {
          int nq = ++tot;
          maxl[nq] = maxl[p] + 1;
          memcpy(ch[nq], ch[q], sizeof(ch[nq]));
          fa[nq] = fa[q];
          fa[q] = fa[np] = nq;
          for (; p && ch[p][x] == q; p = fa[p]) {
            ch[p][x] = nq;
          }
        }
      }
    }
  }
  void build() {
    read(n);
    read(Q);
    tot = last = 1;
    for (int i = 1; i <= n; ++i) {
      last = 1;
      scanf("%s", s + 1);
      int m = strlen(s + 1);
      for (int j = 1; j <= m; ++j) {
        Extend(s[j] - 'a');
        seg.insert(last, i);
      }
      pos[i] = last;
    }
    for (int i = 1; i <= tot; ++i) {
      ++cnt[maxl[i]];
    }
    for (int i = 1; i <= tot; ++i) {
      cnt[i] += cnt[i - 1];
    }
    for (int i = tot; i >= 1; --i) {
      seq[cnt[maxl[i]]--] = i;
    }
    for (int i = tot; i > 1; --i) {
      int u = seq[i];
      seg.merge(fa[u], u);
    }
  }
} sam;
void solve() {
  int l, r, k;
  while (Q--) {
    read(l);
    read(r);
    read(k);
    printf("%lld\n", seg.query(sam.pos[k], l, r));
  }
}
int main() {
  sam.build();
  solve();
  return 0;
}
