#include <bits/stdc++.h>
using namespace std;
const int N = 100000 + 5;
struct Node {
  Node *nxt[26], *fail;
  vector<int> endp, prep, idp;
  vector<Node*> son;
  Node() {
    memset(nxt, 0, sizeof(nxt));
    fail = 0;
  }
} node[N];
queue<Node*> qu;
struct AC_aotumation {
  Node* root;
  int tot;
  void init() {
    tot = 0;
    root = &(node[tot++] = Node());
  }
  void insert(char* s, int id) {
    Node* cur = root;
    for (; *s; s++) {
      int p = *s - 'a';
      if (cur->nxt[p] == NULL) cur->nxt[p] = &(node[tot++] = Node());
      cur = cur->nxt[p];
      cur->prep.push_back(id);
    }
    cur->endp.push_back(id);
  }
  void get_fail() {
    while (!qu.empty()) qu.pop();
    qu.push(root);
    while (!qu.empty()) {
      Node* cur = qu.front();
      qu.pop();
      for (int i = 0; i < 26; i++)
        if (cur->nxt[i]) {
          Node* tmp = cur->fail;
          while (tmp && tmp->nxt[i] == NULL) tmp = tmp->fail;
          cur->nxt[i]->fail = tmp == NULL ? root : tmp->nxt[i];
          qu.push(cur->nxt[i]);
        }
    }
  }
  void deal() {
    for (int i = 1; i < tot; i++) {
      Node* cur = &node[i];
      cur->fail->son.push_back(cur);
    }
  }
} ac;
string str[N];
char s[N];
int cnt[N], l[N], r[N], a[N];
vector<int> vt[N];
int n, m, brute;
long long sum[N], pr[N];
long long dfs(Node* cur, int id) {
  long long ret = 0;
  for (int i = 0; i < cur->prep.size(); i++)
    if (cur->prep[i] == id) ret++;
  for (int i = 0; i < cur->son.size(); i++) {
    ret += dfs(cur->son[i], id);
  }
  for (int i = 0; i < cur->endp.size(); i++) sum[cur->endp[i]] += ret;
  return ret;
}
long long sum2[N];
void update(int x, int y) {
  x++;
  while (x <= n) {
    sum2[x] += y;
    x += x & -x;
  }
}
long long query(int x) {
  x++;
  long long ret = 0;
  while (x) {
    ret += sum2[x];
    x -= x & -x;
  }
  return ret;
}
void dfs2(Node* cur) {
  for (int i = 0; i < cur->endp.size(); i++) {
    update(cur->endp[i], 1);
  }
  for (int i = 0; i < cur->idp.size(); i++) {
    int ii = cur->idp[i];
    for (int j = 0; j < vt[ii].size(); j++) {
      int id = vt[ii][j];
      pr[id] += query(r[id]) - query(l[id] - 1);
    }
  }
  for (int i = 0; i < cur->son.size(); i++) {
    dfs2(cur->son[i]);
  }
  for (int i = 0; i < cur->endp.size(); i++) {
    update(cur->endp[i], -1);
  }
}
int main() {
  scanf("%d%d", &n, &m);
  brute = 333;
  ac.init();
  for (int i = 0; i < n; i++) {
    scanf("%s", s);
    ac.insert(s, i);
    str[i].clear();
    for (int j = 0; s[j]; j++) str[i] += s[j];
  }
  ac.get_fail();
  ac.deal();
  for (int i = 0; i < m; i++) {
    scanf("%d%d%d", &l[i], &r[i], &a[i]);
    l[i]--;
    r[i]--;
    a[i]--;
    vt[a[i]].push_back(i);
  }
  for (int i = 0; i < n; i++) {
    if (vt[i].size() >= brute) {
      memset(sum, 0, sizeof(sum));
      dfs(ac.root, i);
      for (int j = 1; j < n; j++) sum[j] += sum[j - 1];
      for (int j = 0; j < vt[i].size(); j++) {
        int p = vt[i][j];
        pr[p] += sum[r[p]];
        if (l[p] > 0) pr[p] -= sum[l[p] - 1];
      }
    } else {
      Node* cur = ac.root;
      for (int j = 0; j < str[i].size(); j++) {
        cur = cur->nxt[str[i][j] - 'a'];
        cur->idp.push_back(i);
      }
    }
  }
  dfs2(ac.root);
  for (int i = 0; i < m; i++) printf("%I64d\n", pr[i]);
  return 0;
}
