#include <bits/stdc++.h>
using namespace std;
struct vertex {
  map<char, int> next, go;
  int p, link;
  char pch;
  vector<int> leaf;
  unordered_set<int> visited;
  vertex(int p = -1, char pch = -1) : p(p), pch(pch), link(-1) {}
};
vector<vertex> t;
void aho_init() {
  t.clear();
  t.push_back(vertex());
}
int add_string(string s, int id) {
  int v = 0;
  for (char c : s) {
    if (!t[v].next.count(c)) {
      t[v].next[c] = t.size();
      t.push_back(vertex(v, c));
    }
    v = t[v].next[c];
  }
  t[v].leaf.push_back(id);
  return v;
}
void add_visited(int v, int id) { t[v].visited.insert(id); }
int go(int v, char c);
int get_link(int v) {
  if (t[v].link < 0)
    if (!v || !t[v].p)
      t[v].link = 0;
    else
      t[v].link = go(get_link(t[v].p), t[v].pch);
  return t[v].link;
}
int go(int v, char c) {
  if (!t[v].go.count(c))
    if (t[v].next.count(c))
      t[v].go[c] = t[v].next[c];
    else
      t[v].go[c] = v == 0 ? 0 : go(get_link(v), c);
  return t[v].go[c];
}
const int N = 3e5;
vector<int> g[N];
int last[N];
string s[N];
int n, q, B;
long long tot[400], sum[N];
struct Query {
  int l, r, k, id;
};
int dfs(int x, int i, vector<long long>& partials) {
  int cnt = 0;
  if (t[x].visited.count(i)) ++cnt, t[x].visited.erase(i);
  for (auto v : g[x]) cnt += dfs(v, i, partials);
  for (auto v : t[x].leaf) partials[v] += cnt;
  return cnt;
}
void solveLarge(vector<Query>& q, int i, vector<long long>& res) {
  vector<long long> partials(n + 1, 0);
  dfs(0, i, partials);
  for (int i = 1; i < n + 1; i++) partials[i] += partials[i - 1];
  for (auto query : q) {
    res[query.id] = partials[query.r] - partials[query.l];
  }
}
void add(int i, int val) {
  while (i < N && i % B) {
    sum[i++] += val;
  }
  i /= B;
  while (i <= n / B) tot[i++] += val;
}
int get(int i) { return sum[i] + tot[i / B]; }
void dfs2(int x, vector<vector<Query>>& queries, vector<long long>& res) {
  for (auto v : t[x].leaf) add(v, 1);
  for (auto v : t[x].visited) {
    for (auto q : queries[v]) {
      res[q.id] += get(q.r) - get(q.l);
    }
  }
  for (auto v : g[x]) dfs2(v, queries, res);
  for (auto v : t[x].leaf) add(v, -1);
}
void solveSmall(vector<vector<Query>>& queries, vector<long long>& res) {
  dfs2(0, queries, res);
}
int main() {
  cin >> n >> q;
  B = sqrt(n);
  for (int i = 0; i < n; i++) cin >> s[i];
  aho_init();
  for (int i = 0; i < n; i++) {
    add_string(s[i], i + 1);
  }
  for (int i = 0; i < n; i++) {
    int cur = 0;
    add_visited(cur, i);
    for (char c : s[i]) {
      cur = go(cur, c);
      add_visited(cur, i);
    }
    last[i] = cur;
  }
  for (int i = 1; i < ((int)t.size()); i++) {
    g[get_link(i)].push_back(i);
  }
  vector<Query> queries;
  for (int i = 0; i < q; i++) {
    int l, r, k;
    cin >> l >> r >> k;
    queries.push_back({l - 1, r, k - 1, i});
  }
  vector<vector<Query>> large(n);
  vector<vector<Query>> small(n);
  for (auto query : queries) {
    if (((int)s[query.k].size()) >= B) {
      large[query.k].push_back(query);
    } else {
      small[query.k].push_back(query);
    }
  }
  vector<long long> res(q, 0);
  for (int i = 0; i < n; i++) {
    if (((int)large[i].size())) solveLarge(large[i], i, res);
  }
  solveSmall(small, res);
  for (int i = 0; i < q; i++) cout << res[i] << endl;
  return 0;
}
