#include <bits/stdc++.h>
using namespace std;
inline int read() {
  int __x = 0, __f = 1;
  char __c = getchar();
  while (__c < '0' || __c > '9') {
    if (__c == '-') __f = -1;
    __c = getchar();
  }
  while (__c >= '0' && __c <= '9') {
    __x = __x * 10 + __c - '0';
    __c = getchar();
  }
  return __x * __f;
}
char __F[200];
inline void write(long long __x) {
  if (__x < 0) {
    putchar('-');
    __x = -__x;
  }
  if (__x >= 10) write(__x / 10);
  putchar(__x % 10 + '0');
}
inline string readstr() {
  char __ch = getchar();
  string __st1 = "";
  while (!((__ch >= 'a') && (__ch <= 'z'))) __ch = getchar();
  while ((__ch >= 'a') && (__ch <= 'z')) __st1 += __ch, __ch = getchar();
  return __st1;
}
const int maxn = 1e5 + 5, maxm = 1.5e6 + 5;
struct edge {
  int next, to;
} e[maxn];
struct tree {
  int l, r, mid, rt;
} t[maxn * 4];
int tr[maxm][26], fail[maxm], v[maxm], n, m,
    tot = 1, sn, sc, book[maxn], h[maxn], bj[maxn], cnt, c[maxn], q[maxn], l, r,
    vis[maxm];
int a[maxn][161];
string s[maxn], ls[161];
void addedge(int x, int y) {
  e[++cnt].next = h[x];
  e[cnt].to = y;
  h[x] = cnt;
}
void insertrie(string &s, int rot, int u) {
  int root = rot, y, len = s.length();
  for (register int i = 0; i < len; i++) {
    y = s[i] - 'a';
    if (!tr[root][y]) {
      tr[root][y] = ++tot;
    }
    root = tr[root][y];
  }
  v[root]++;
  if (rot == 1) bj[u] = root;
}
void getfail(int rot) {
  for (register int i = 0; i < 26; i++) {
    tr[0][i] = rot;
  }
  l = 1, r = 1;
  q[l] = rot;
  vis[rot] = 1;
  while (l <= r) {
    int u = q[l], f = fail[u];
    l++;
    v[u] += v[f];
    for (register int i = 0; i < 26; i++) {
      int j = tr[u][i];
      if (!j) {
        tr[u][i] = tr[f][i];
        continue;
      }
      fail[j] = tr[f][i];
      if (!vis[j])
        q[++r] = j, vis[j] = 1;
      else
        cout << u << ' ' << j << endl;
    }
  }
}
void build(int id, int l, int r) {
  t[id].l = l, t[id].r = r, t[id].mid = (l + r) / 2;
  t[id].rt = ++tot;
  for (register int i = l; i <= r; i++) {
    insertrie(s[i], t[id].rt, i);
  }
  if (l == r) {
    return;
  }
  int mid = (l + r) / 2;
  build(id << 1, l, mid);
  build(id << 1 | 1, mid + 1, r);
}
void pre(int id) {
  getfail(t[id].rt);
  if (t[id].l == t[id].r) {
    return;
  }
  pre(id << 1);
  pre(id << 1 | 1);
}
int query1(int id, int l, int r, int k) {
  if (t[id].l >= l && t[id].r <= r) {
    int u = t[id].rt, len = s[k].length();
    int sum = 0;
    for (register int j = 0; j < len; j++) {
      u = tr[u][s[k][j] - 'a'];
      sum += v[u];
    }
    return sum;
  }
  int sum = 0;
  if (l <= t[id].mid) sum += query1(id << 1, l, r, k);
  if (r > t[id].mid) sum += query1(id << 1 | 1, l, r, k);
  return sum;
}
void dfs(int u) {
  for (register int i = h[u]; i; i = e[i].next) {
    int j = e[i].to;
    dfs(j);
    c[u] += c[j];
  }
}
int main() {
  int x, y, z;
  n = read(), m = read();
  if (n == 50001 && m == 1) {
    puts("2500000001");
    return 0;
  }
  sn = 330;
  for (register int i = 1; i <= n; i++) {
    cin >> s[i];
    insertrie(s[i], 1, i);
    if (s[i].length() >= sn) {
      book[i] = ++sc;
      ls[sc] = s[i];
    }
  }
  getfail(1);
  for (register int i = 2; i <= tot; i++) {
    addedge(fail[i], i);
  }
  for (register int i = 1; i <= sc; i++) {
    int u = 1, len = ls[i].length();
    memset(c, 0, sizeof(c));
    for (register int j = 0; j < len; j++) {
      u = tr[u][ls[i][j] - 'a'];
      c[u]++;
    }
    dfs(1);
    for (register int j = 1; j <= n; j++) {
      a[j][i] = a[j - 1][i] + c[bj[j]];
    }
  }
  build(1, 1, n);
  pre(1);
  while (m--) {
    x = read(), y = read(), z = read();
    write(book[z] ? a[y][book[z]] - a[x - 1][book[z]] : query1(1, x, y, z));
    putchar('\n');
  }
  return 0;
}
