#include <bits/stdc++.h>
#define FOR(i, n) for(int i = 0; i < (n); ++i)
#define REP(i, a, b) for(int i = (a); i < (b); ++i)
#define TRAV(i, a) for(auto & i : (a))
#define SZ(x) ((int)(x).size())
#define PR std::pair
#define MP std::make_pair
#define X first
#define Y second
typedef long long ll;
typedef std::pair<int, int> PII;
typedef std::vector<int> VI;

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template<typename T>
using ordered_set = tree<
T,
null_type,
std::less<T>,
rb_tree_tag,
tree_order_statistics_node_update>;

//X.find_by_order(k); - zwraca iterator na k-ty element (numeracja od zerowego)
//X.order_of_key(k); - zwraca liczbę elementów ostro mniejszych niż k

// https://doi.org/10.1145/1217856.1217858
inline bool leq(int a1, int a2, int b1, int b2){
	return a1 < b1 || (a1 == b1 && a2 <= b2);
}
inline bool leq(int a1, int a2, int a3, int b1, int b2, int b3){
	return a1 < b1 || (a1 == b1 && leq(a2, a3, b2, b3));
}
void radix(int *a, int *b, int *r, int n, int K){
	int *c = new int[K+1];
	for(int i = 0; i <= K; ++i) c[i] = 0;
	for(int i = 0; i < n; ++i) c[r[a[i]]]++;
	for(int i = 0, sum = 0, t = 0; i <= K; ++i) t = c[i], c[i] = sum, sum += t;
	for(int i = 0; i < n; ++i) b[c[r[a[i]]]++] = a[i];
	delete [] c;
}
// A = {1..K}
// T[0..n-1] - word
// T[n] = T[n+1] = T[n+2] = 0
// SA[0..n-1] - output
void suffix_array(int *T, int *SA, int n, int K){
	if(n == 1){
		SA[0] = 0;
		return;
	}
	int n0 = (n+2)/3, n1 = (n+1)/3, n2 = n/3, n02=n0+n2;
	int *R = new int[n02+3];
	int *SA12 = new int[n02+3];
	int *R0 = new int[n02];
	int *SA0 = new int[n02];
	for(int i = 0; i < 3; ++i) R[n02+i] = SA12[n02+i] = 0;
	for(int i = 0, j = 0; i < n+n0-n1; ++i) if(i%3) R[j++] = i;
	radix(R, SA12, T+2, n02, K);
	radix(SA12, R, T+1, n02, K);
	radix(R, SA12, T, n02, K);
	int name = 0, c0 = -1, c1 = -1, c2 = -1;
	for(int i = 0; i < n02; ++i){
		if(T[SA12[i]] != c0 || T[SA12[i]+1] != c1 || T[SA12[i]+2] != c2)
			name++, c0 = T[SA12[i]], c1 = T[SA12[i]+1], c2 = T[SA12[i]+2];
		if(SA12[i]%3 == 1) R[SA12[i]/3] = name;
		else R[SA12[i]/3+n0] = name;
	}
	if(name < n02){
		suffix_array(R, SA12, n02, name);
		for(int i = 0; i < n02; ++i) R[SA12[i]] = i+1;
	}else for(int i = 0; i < n02; ++i) SA12[R[i]-1] = i;
	for(int i = 0, j = 0; i < n02; ++i) if(SA12[i] < n0) R0[j++] = 3*SA12[i];
	radix(R0, SA0, T, n0, K);
	for(int p = 0, t = n0-n1, k = 0; k < n; ++k){
		#define GetI() (SA12[t] < n0 ? SA12[t] * 3 + 1 : (SA12[t] - n0) * 3 + 2)
		int i = GetI();
		int j = SA0[p];
		if(SA12[t] < n0 ?
			leq(T[i], R[SA12[t]+n0], T[j], R[j/3]) :
			leq(T[i], T[i+1], R[SA12[t]-n0+1], T[j], T[j+1], R[j/3+n0])){
			SA[k] = i, t++;
			if(t == n02) for(k++; p < n0; p++, k++) SA[k] = SA0[p];
		}else{
			SA[k] = j; p++;
			if(p == n0) for(k++; t < n02; t++, k++) SA[k] = GetI();
		}
	}
	delete[] R; delete[] SA12; delete[] SA0; delete[] R0;
}

// lcp[0..n-2] - output
void kasai(int *T, int *sa, int *lcp, int n){
	int k = 0;
	int *rank = new int[n];
	for(int i = 0; i < n; ++i) rank[sa[i]] = i;
	for(int i = 0; i < n; ++i, k?k--:0){
		if(rank[i] == n-1){
			k = 0; continue;
		}
		int j = sa[rank[i]+1];
		while(i+k<n && j+k<n && T[i+k] == T[j+k]) k++;
		lcp[rank[i]] = k;
	}
	delete[] rank;
}

// A = {1..K}
// T[0..n-1] - word
// T[n] = T[n+1] = T[n+2] = 0
// SA[0..n-1] - output
// void suffix_array(int *T, int *SA, int n, int K)

const int M = 400010;
int T[M], sa[M], lcp[M], rank[M];
/*
const int MOD = 1000000007;
const int P = 5315;
int hash[M], pw[M];

bool same(int a, int b, int l){
	a++;b++;
	int h1 = (hash[a+l-1]-hash[a]*pw[l])%MOD;
	if(h1 < 0) h1 += MOD;
	int h2 = (hash[b+l-1]-hash[b]*pw[l])%MOD;
	if(h2 < 0) h2 += MOD;
	return h1 == h2;
}*/

const int INF = 1000000666;
struct Tree{
	int BOTTOM;
	VI t;
	int szzz;
	void build(VI A){
		szzz = SZ(A);
		BOTTOM = 1;
		while(BOTTOM < SZ(A)) BOTTOM *= 2;
		t.resize(BOTTOM*2, INF);
		FOR(i, SZ(A)) t[i+BOTTOM] = A[i];
		for(int i = BOTTOM-1; i >= 1; --i) t[i] = std::min(t[i<<1], t[(i<<1)+1]);
	}

	int query(int a, int b){
		assert(a <= b && a >= 0 && b < szzz);
		a += BOTTOM;
		b += BOTTOM+1;
		int ret = INF;
		while(a < b){
			if(a&1) ret = std::min(ret, t[a++]);
			if(b&1) ret = std::min(ret, t[--b]);
			a>>=1;b>>=1;
		}
		return ret;
	}
};

int main(){
	std::ios_base::sync_with_stdio(false);
	std::cin.tie(0);
	int n, q;
	std::cin >> n >> q;
	std::vector<VI> A(n);

	VI slo;
	VI pss(n);
	FOR(i, n){
		std::string s;
		std::cin >> s;
		pss[i] = SZ(slo);
		TRAV(c, s) A[i].push_back(SZ(slo)), slo.push_back(c-'a'+2);
		slo.push_back(1);
	}
/*
	hash[0] = 0;
	pw[0] = 1;
	REP(i, 1, M) pw[i] = (1ll*pw[i-1]*P)%MOD;
	FOR(i, SZ(slo)){
		hash[i+1] = (1ll*hash[i]*P + slo[i])%MOD;
	}
*/
	FOR(i, SZ(slo)) T[i] = slo[i];
	REP(i, SZ(slo), SZ(slo)+3) T[i] = 0;

	suffix_array(T, sa, SZ(slo), 50);
	kasai(T, sa, lcp, SZ(slo));

	FOR(i, SZ(slo)) rank[sa[i]] = i;
	/*FOR(i, SZ(slo)) std::cout << slo[i] << " ";
	std::cout << "\n";
	FOR(i, SZ(slo)) std::cout << rank[i] << " ";
	std::cout << "\n";*/

	Tree tree;
	VI hehe(SZ(slo)-1);
	FOR(i, SZ(slo)-1) hehe[i] = lcp[i];
	tree.build(hehe);

	VI ans(q);
	std::vector<std::vector<PII> > events(n);
	std::vector<PII> prze(q);

/*
	FOR(i, SZ(slo)) std::cerr << (slo[i] == 1 ? "|" : std::to_string(slo[i])) << " ";
	std::cerr << std::endl;
*/
	FOR(i, q){
		int l, r, k;
		std::cin >> l >> r >> k;
		l--;r--;k--;
		int p = rank[pss[k]];

		int left = 0;
		int right = p;
		while(left < right){
			int mid = (left+right)/2;
			if(tree.query(mid, p-1) < SZ(A[k])) left = mid+1;
			else right = mid;
		}

		int L = left;

		left = p;
		right = SZ(slo);
		while(left < right){
			int mid = (left+right)/2;
			assert(mid-1 < SZ(slo)-1);
			if(tree.query(p, mid-1) >= SZ(A[k])) left = mid+1;
			else right = mid;
		}
		left--;

		int R = left;

		prze[i] = MP(L, R);

		assert(L <= R);
		if(l > 0) events[l-1].push_back(MP(i, -1));
		events[r].push_back(MP(i, 1));
	}

	ordered_set<int> set;

	auto ask = [&](int a, int b){
		return set.order_of_key(b+1) - set.order_of_key(a);
	};

	FOR(i, n){
		TRAV(j, A[i]) set.insert(rank[j]);
		TRAV(ev, events[i]){
			int a = prze[ev.X].X;
			int b = prze[ev.X].Y;
			ans[ev.X] += ev.Y*ask(a, b);
		}
	}

	FOR(i, q) std::cout << ans[i] << "\n";

	return 0;
}


#include <bits/stdc++.h>
#define FOR(i, n) for(int i = 0; i < (n); ++i)
#define REP(i, a, b) for(int i = (a); i < (b); ++i)
#define TRAV(i, a) for(auto & i : (a))
#define SZ(x) ((int)(x).size())
#define PR std::pair
#define MP std::make_pair
#define X first
#define Y second
typedef long long ll;
typedef std::pair<int, int> PII;
typedef std::vector<int> VI;

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template<typename T>
using ordered_set = tree<
T,
null_type,
std::less<T>,
rb_tree_tag,
tree_order_statistics_node_update>;

//X.find_by_order(k); - zwraca iterator na k-ty element (numeracja od zerowego)
//X.order_of_key(k); - zwraca liczbę elementów ostro mniejszych niż k

// https://doi.org/10.1145/1217856.1217858
inline bool leq(int a1, int a2, int b1, int b2){
	return a1 < b1 || (a1 == b1 && a2 <= b2);
}
inline bool leq(int a1, int a2, int a3, int b1, int b2, int b3){
	return a1 < b1 || (a1 == b1 && leq(a2, a3, b2, b3));
}
void radix(int *a, int *b, int *r, int n, int K){
	int *c = new int[K+1];
	for(int i = 0; i <= K; ++i) c[i] = 0;
	for(int i = 0; i < n; ++i) c[r[a[i]]]++;
	for(int i = 0, sum = 0, t = 0; i <= K; ++i) t = c[i], c[i] = sum, sum += t;
	for(int i = 0; i < n; ++i) b[c[r[a[i]]]++] = a[i];
	delete [] c;
}
// A = {1..K}
// T[0..n-1] - word
// T[n] = T[n+1] = T[n+2] = 0
// SA[0..n-1] - output
void suffix_array(int *T, int *SA, int n, int K){
	if(n == 1){
		SA[0] = 0;
		return;
	}
	int n0 = (n+2)/3, n1 = (n+1)/3, n2 = n/3, n02=n0+n2;
	int *R = new int[n02+3];
	int *SA12 = new int[n02+3];
	int *R0 = new int[n02];
	int *SA0 = new int[n02];
	for(int i = 0; i < 3; ++i) R[n02+i] = SA12[n02+i] = 0;
	for(int i = 0, j = 0; i < n+n0-n1; ++i) if(i%3) R[j++] = i;
	radix(R, SA12, T+2, n02, K);
	radix(SA12, R, T+1, n02, K);
	radix(R, SA12, T, n02, K);
	int name = 0, c0 = -1, c1 = -1, c2 = -1;
	for(int i = 0; i < n02; ++i){
		if(T[SA12[i]] != c0 || T[SA12[i]+1] != c1 || T[SA12[i]+2] != c2)
			name++, c0 = T[SA12[i]], c1 = T[SA12[i]+1], c2 = T[SA12[i]+2];
		if(SA12[i]%3 == 1) R[SA12[i]/3] = name;
		else R[SA12[i]/3+n0] = name;
	}
	if(name < n02){
		suffix_array(R, SA12, n02, name);
		for(int i = 0; i < n02; ++i) R[SA12[i]] = i+1;
	}else for(int i = 0; i < n02; ++i) SA12[R[i]-1] = i;
	for(int i = 0, j = 0; i < n02; ++i) if(SA12[i] < n0) R0[j++] = 3*SA12[i];
	radix(R0, SA0, T, n0, K);
	for(int p = 0, t = n0-n1, k = 0; k < n; ++k){
		#define GetI() (SA12[t] < n0 ? SA12[t] * 3 + 1 : (SA12[t] - n0) * 3 + 2)
		int i = GetI();
		int j = SA0[p];
		if(SA12[t] < n0 ?
			leq(T[i], R[SA12[t]+n0], T[j], R[j/3]) :
			leq(T[i], T[i+1], R[SA12[t]-n0+1], T[j], T[j+1], R[j/3+n0])){
			SA[k] = i, t++;
			if(t == n02) for(k++; p < n0; p++, k++) SA[k] = SA0[p];
		}else{
			SA[k] = j; p++;
			if(p == n0) for(k++; t < n02; t++, k++) SA[k] = GetI();
		}
	}
	delete[] R; delete[] SA12; delete[] SA0; delete[] R0;
}

// lcp[0..n-2] - output
void kasai(int *T, int *sa, int *lcp, int n){
	int k = 0;
	int *rank = new int[n];
	for(int i = 0; i < n; ++i) rank[sa[i]] = i;
	for(int i = 0; i < n; ++i, k?k--:0){
		if(rank[i] == n-1){
			k = 0; continue;
		}
		int j = sa[rank[i]+1];
		while(i+k<n && j+k<n && T[i+k] == T[j+k]) k++;
		lcp[rank[i]] = k;
	}
	delete[] rank;
}

// A = {1..K}
// T[0..n-1] - word
// T[n] = T[n+1] = T[n+2] = 0
// SA[0..n-1] - output
// void suffix_array(int *T, int *SA, int n, int K)

const int M = 400010;
int T[M], sa[M], lcp[M], rank[M];
/*
const int MOD = 1000000007;
const int P = 5315;
int hash[M], pw[M];

bool same(int a, int b, int l){
	a++;b++;
	int h1 = (hash[a+l-1]-hash[a]*pw[l])%MOD;
	if(h1 < 0) h1 += MOD;
	int h2 = (hash[b+l-1]-hash[b]*pw[l])%MOD;
	if(h2 < 0) h2 += MOD;
	return h1 == h2;
}*/

const int INF = 1000000666;
struct Tree{
	int BOTTOM;
	VI t;
	int szzz;
	void build(VI A){
		szzz = SZ(A);
		BOTTOM = 1;
		while(BOTTOM < SZ(A)) BOTTOM *= 2;
		t.resize(BOTTOM*2, INF);
		FOR(i, SZ(A)) t[i+BOTTOM] = A[i];
		for(int i = BOTTOM-1; i >= 1; --i) t[i] = std::min(t[i<<1], t[(i<<1)+1]);
	}

	int query(int a, int b){
		assert(a <= b && a >= 0 && b < szzz);
		a += BOTTOM;
		b += BOTTOM+1;
		int ret = INF;
		while(a < b){
			if(a&1) ret = std::min(ret, t[a++]);
			if(b&1) ret = std::min(ret, t[--b]);
			a>>=1;b>>=1;
		}
		return ret;
	}
};

int main(){
	std::ios_base::sync_with_stdio(false);
	std::cin.tie(0);
	int n, q;
	std::cin >> n >> q;
	std::vector<VI> A(n);

	VI slo;
	VI pss(n);
	FOR(i, n){
		std::string s;
		std::cin >> s;
		pss[i] = SZ(slo);
		TRAV(c, s) A[i].push_back(SZ(slo)), slo.push_back(c-'a'+2);
		slo.push_back(1);
	}
/*
	hash[0] = 0;
	pw[0] = 1;
	REP(i, 1, M) pw[i] = (1ll*pw[i-1]*P)%MOD;
	FOR(i, SZ(slo)){
		hash[i+1] = (1ll*hash[i]*P + slo[i])%MOD;
	}
*/
	FOR(i, SZ(slo)) T[i] = slo[i];
	REP(i, SZ(slo), SZ(slo)+3) T[i] = 0;

	suffix_array(T, sa, SZ(slo), 50);
	kasai(T, sa, lcp, SZ(slo));

	FOR(i, SZ(slo)) rank[sa[i]] = i;
	/*FOR(i, SZ(slo)) std::cout << slo[i] << " ";
	std::cout << "\n";
	FOR(i, SZ(slo)) std::cout << rank[i] << " ";
	std::cout << "\n";*/

	Tree tree;
	VI hehe(SZ(slo)-1);
	FOR(i, SZ(slo)-1) hehe[i] = lcp[i];
	tree.build(hehe);

	VI ans(q);
	std::vector<std::vector<PII> > events(n);
	std::vector<PII> prze(q);

/*
	FOR(i, SZ(slo)) std::cerr << (slo[i] == 1 ? "|" : std::to_string(slo[i])) << " ";
	std::cerr << std::endl;
*/
	FOR(i, q){
		int l, r, k;
		std::cin >> l >> r >> k;
		l--;r--;k--;
		int p = rank[pss[k]];

		int left = 0;
		int right = p;
		while(left < right){
			int mid = (left+right)/2;
			if(tree.query(mid, p-1) < SZ(A[k])) left = mid+1;
			else right = mid;
		}

		int L = left;

		left = p;
		right = SZ(slo)-1;
		while(left < right){
			int mid = (left+right)/2;
			assert(mid-1 < SZ(slo)-1);
			if(tree.query(p, mid-1) >= SZ(A[k])) left = mid+1;
			else right = mid;
		}
		left--;

		int R = left;

		prze[i] = MP(L, R);

		assert(L <= R);
		if(l > 0) events[l-1].push_back(MP(i, -1));
		events[r].push_back(MP(i, 1));
	}

	ordered_set<int> set;

	auto ask = [&](int a, int b){
		return set.order_of_key(b+1) - set.order_of_key(a);
	};

	FOR(i, n){
		TRAV(j, A[i]) set.insert(rank[j]);
		TRAV(ev, events[i]){
			int a = prze[ev.X].X;
			int b = prze[ev.X].Y;
			ans[ev.X] += ev.Y*ask(a, b);
		}
	}

	FOR(i, q) std::cout << ans[i] << "\n";

	return 0;
}


#include <bits/stdc++.h>
#define FOR(i, n) for(int i = 0; i < (n); ++i)
#define REP(i, a, b) for(int i = (a); i < (b); ++i)
#define TRAV(i, a) for(auto & i : (a))
#define SZ(x) ((int)(x).size())
#define PR std::pair
#define MP std::make_pair
#define X first
#define Y second
typedef long long ll;
typedef std::pair<int, int> PII;
typedef std::vector<int> VI;

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template<typename T>
using ordered_set = tree<
T,
null_type,
std::less<T>,
rb_tree_tag,
tree_order_statistics_node_update>;

//X.find_by_order(k); - zwraca iterator na k-ty element (numeracja od zerowego)
//X.order_of_key(k); - zwraca liczbę elementów ostro mniejszych niż k

// https://doi.org/10.1145/1217856.1217858
inline bool leq(int a1, int a2, int b1, int b2){
	return a1 < b1 || (a1 == b1 && a2 <= b2);
}
inline bool leq(int a1, int a2, int a3, int b1, int b2, int b3){
	return a1 < b1 || (a1 == b1 && leq(a2, a3, b2, b3));
}
void radix(int *a, int *b, int *r, int n, int K){
	int *c = new int[K+1];
	for(int i = 0; i <= K; ++i) c[i] = 0;
	for(int i = 0; i < n; ++i) c[r[a[i]]]++;
	for(int i = 0, sum = 0, t = 0; i <= K; ++i) t = c[i], c[i] = sum, sum += t;
	for(int i = 0; i < n; ++i) b[c[r[a[i]]]++] = a[i];
	delete [] c;
}
// A = {1..K}
// T[0..n-1] - word
// T[n] = T[n+1] = T[n+2] = 0
// SA[0..n-1] - output
void suffix_array(int *T, int *SA, int n, int K){
	if(n == 1){
		SA[0] = 0;
		return;
	}
	int n0 = (n+2)/3, n1 = (n+1)/3, n2 = n/3, n02=n0+n2;
	int *R = new int[n02+3];
	int *SA12 = new int[n02+3];
	int *R0 = new int[n02];
	int *SA0 = new int[n02];
	for(int i = 0; i < 3; ++i) R[n02+i] = SA12[n02+i] = 0;
	for(int i = 0, j = 0; i < n+n0-n1; ++i) if(i%3) R[j++] = i;
	radix(R, SA12, T+2, n02, K);
	radix(SA12, R, T+1, n02, K);
	radix(R, SA12, T, n02, K);
	int name = 0, c0 = -1, c1 = -1, c2 = -1;
	for(int i = 0; i < n02; ++i){
		if(T[SA12[i]] != c0 || T[SA12[i]+1] != c1 || T[SA12[i]+2] != c2)
			name++, c0 = T[SA12[i]], c1 = T[SA12[i]+1], c2 = T[SA12[i]+2];
		if(SA12[i]%3 == 1) R[SA12[i]/3] = name;
		else R[SA12[i]/3+n0] = name;
	}
	if(name < n02){
		suffix_array(R, SA12, n02, name);
		for(int i = 0; i < n02; ++i) R[SA12[i]] = i+1;
	}else for(int i = 0; i < n02; ++i) SA12[R[i]-1] = i;
	for(int i = 0, j = 0; i < n02; ++i) if(SA12[i] < n0) R0[j++] = 3*SA12[i];
	radix(R0, SA0, T, n0, K);
	for(int p = 0, t = n0-n1, k = 0; k < n; ++k){
		#define GetI() (SA12[t] < n0 ? SA12[t] * 3 + 1 : (SA12[t] - n0) * 3 + 2)
		int i = GetI();
		int j = SA0[p];
		if(SA12[t] < n0 ?
			leq(T[i], R[SA12[t]+n0], T[j], R[j/3]) :
			leq(T[i], T[i+1], R[SA12[t]-n0+1], T[j], T[j+1], R[j/3+n0])){
			SA[k] = i, t++;
			if(t == n02) for(k++; p < n0; p++, k++) SA[k] = SA0[p];
		}else{
			SA[k] = j; p++;
			if(p == n0) for(k++; t < n02; t++, k++) SA[k] = GetI();
		}
	}
	delete[] R; delete[] SA12; delete[] SA0; delete[] R0;
}

// lcp[0..n-2] - output
void kasai(int *T, int *sa, int *lcp, int n){
	int k = 0;
	int *rank = new int[n];
	for(int i = 0; i < n; ++i) rank[sa[i]] = i;
	for(int i = 0; i < n; ++i, k?k--:0){
		if(rank[i] == n-1){
			k = 0; continue;
		}
		int j = sa[rank[i]+1];
		while(i+k<n && j+k<n && T[i+k] == T[j+k]) k++;
		lcp[rank[i]] = k;
	}
	delete[] rank;
}

// A = {1..K}
// T[0..n-1] - word
// T[n] = T[n+1] = T[n+2] = 0
// SA[0..n-1] - output
// void suffix_array(int *T, int *SA, int n, int K)

const int M = 400010;
int T[M], sa[M], lcp[M], rank[M];
/*
const int MOD = 1000000007;
const int P = 5315;
int hash[M], pw[M];

bool same(int a, int b, int l){
	a++;b++;
	int h1 = (hash[a+l-1]-hash[a]*pw[l])%MOD;
	if(h1 < 0) h1 += MOD;
	int h2 = (hash[b+l-1]-hash[b]*pw[l])%MOD;
	if(h2 < 0) h2 += MOD;
	return h1 == h2;
}*/

const int INF = 1000000666;
struct Tree{
	int BOTTOM;
	VI t;
	int szzz;
	void build(VI A){
		szzz = SZ(A);
		BOTTOM = 1;
		while(BOTTOM < SZ(A)) BOTTOM *= 2;
		t.resize(BOTTOM*2, INF);
		FOR(i, SZ(A)) t[i+BOTTOM] = A[i];
		for(int i = BOTTOM-1; i >= 1; --i) t[i] = std::min(t[i<<1], t[(i<<1)+1]);
	}

	int query(int a, int b){
		assert(a <= b && a >= 0 && b < szzz);
		a += BOTTOM;
		b += BOTTOM+1;
		int ret = INF;
		while(a < b){
			if(a&1) ret = std::min(ret, t[a++]);
			if(b&1) ret = std::min(ret, t[--b]);
			a>>=1;b>>=1;
		}
		return ret;
	}
};

int main(){
	std::ios_base::sync_with_stdio(false);
	std::cin.tie(0);
	int n, q;
	std::cin >> n >> q;
	std::vector<VI> A(n);

	VI slo;
	VI pss(n);
	FOR(i, n){
		std::string s;
		std::cin >> s;
		pss[i] = SZ(slo);
		TRAV(c, s) A[i].push_back(SZ(slo)), slo.push_back(c-'a'+2);
		slo.push_back(1);
	}
/*
	hash[0] = 0;
	pw[0] = 1;
	REP(i, 1, M) pw[i] = (1ll*pw[i-1]*P)%MOD;
	FOR(i, SZ(slo)){
		hash[i+1] = (1ll*hash[i]*P + slo[i])%MOD;
	}
*/
	FOR(i, SZ(slo)) T[i] = slo[i];
	REP(i, SZ(slo), SZ(slo)+3) T[i] = 0;

	suffix_array(T, sa, SZ(slo), 50);
	kasai(T, sa, lcp, SZ(slo));

	FOR(i, SZ(slo)) rank[sa[i]] = i;
	/*FOR(i, SZ(slo)) std::cout << slo[i] << " ";
	std::cout << "\n";
	FOR(i, SZ(slo)) std::cout << rank[i] << " ";
	std::cout << "\n";*/

	Tree tree;
	VI hehe(SZ(slo)-1);
	FOR(i, SZ(slo)-1) hehe[i] = lcp[i];
	tree.build(hehe);

	VI ans(q);
	std::vector<std::vector<PII> > events(n);
	std::vector<PII> prze(q);

/*
	FOR(i, SZ(slo)) std::cerr << (slo[i] == 1 ? "|" : std::to_string(slo[i])) << " ";
	std::cerr << std::endl;
*/
	FOR(i, q){
		int l, r, k;
		std::cin >> l >> r >> k;
		l--;r--;k--;
		int p = rank[pss[k]];

		int left = 0;
		int right = p;
		while(left < right){
			int mid = (left+right)/2;
			if(tree.query(mid, p-1) < SZ(A[k])) left = mid+1;
			else right = mid;
		}

		int L = left;

		left = p;
		right = SZ(slo);
		while(left < right){
			int mid = (left+right)/2;
			if(tree.query(p, mid-1) >= SZ(A[k])) left = mid+1;
			else right = mid;
		}
		left--;

		int R = left;

		prze[i] = MP(L, R);

		assert(L <= R);
		if(l > 0) events[l-1].push_back(MP(i, -1));
		events[r].push_back(MP(i, 1));
	}

	ordered_set<int> set;

	auto ask = [&](int a, int b){
		return set.order_of_key(b+1) - set.order_of_key(a);
	};

	FOR(i, n){
		TRAV(j, A[i]) set.insert(rank[j]);
		TRAV(ev, events[i]){
			int a = prze[ev.X].X;
			int b = prze[ev.X].Y;
			ans[ev.X] += ev.Y*ask(a, b);
		}
	}

	FOR(i, q) std::cout << ans[i] << "\n";

	return 0;
}


#ifdef ONPC
# define _GLIBCXX_DEBUG
#define deb(a) cerr << "nu smotri pidor " << #a << " = " << a << endl;
#else
#define deb(a)
#endif
#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma,sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

using namespace std;

typedef int ll;
typedef long double ld;
ll MOD = 1e9 + 7;

const int N = 410000;
vector<ll> tr[N];
class SegmentTreeFC {

    int sz;
    vector< vector<int> > t, tl, tr;

    void build(int v, int vl, int vr, const vector<int> &a) {
        if (vl == vr) {
            t[v].push_back(a[vl]);
            return;
        }
        int vm = vl + (vr - vl) / 2;
        build(2 * v + 1, vl, vm, a);
        build(2 * v + 2, vm + 1, vr, a);

        int l = 2 * v + 1, r = 2 * v + 2;
        int ls = t[l].size(), rs = t[r].size(), ts = ls + rs;
        t[v].resize(ts);
        tl[v].resize(ts + 1);
        tr[v].resize(ts + 1);
        tl[v][ts] = ls;
        tr[v][ts] = rs;
        for (int i = ts - 1, li = ls - 1, ri = rs - 1; i >= 0; i--) {
            if (li < 0)
                t[v][i] = t[r][ri--];
            else if (ri < 0)
                t[v][i] = t[l][li--];
            else if (t[l][li] > t[r][ri])
                t[v][i] = t[l][li--];
            else
                t[v][i] = t[r][ri--];
            tl[v][i] = (li >= 0 && t[l][li] >= t[v][i] ? li : li + 1);
            tr[v][i] = (ri >= 0 && t[r][ri] >= t[v][i] ? ri : ri + 1);
        }
    }

    int query(int v, int vl, int vr, int l, int r, int k, int ub) const {
        if (ub == -1)
            ub = upper_bound(t[v].begin(), t[v].end(), k) - t[v].begin();
        if (r < vl || vr < l)
            return 0;
        if (l <= vl && vr <= r)
            return vr - vl + 1 - ub;
        int vm = vl + (vr - vl) / 2;
        int ql = query(2 * v + 1, vl, vm, l, r, k, tl[v][ub]);
        int qr = query(2 * v + 2, vm + 1, vr, l, r, k, tr[v][ub]);
        return ql + qr;
    }

public:

    SegmentTreeFC(const vector<int> &a) {
        sz = a.size();
        t.resize(4 * sz);
        tl.resize(4 * sz);
        tr.resize(4 * sz);
        build(0, 0, sz - 1, a);
    }

    int query(int l, int r, int k) const {
        return query(0, 0, sz - 1, l, r, k, -1);
    }

};

void inc(ll i, ll x){
    for (;i < N; i = ((i + 1) | i)){
        tr[i].push_back(x);
     //   sort(tr[i].begin(), tr[i].end());
    }
}
ll sm(ll i, ll r, ll l){
    ll ans = 0;
    for (; i > -1; i = ((i + 1) & i) - 1){
        ans += lower_bound(tr[i].begin(), tr[i].end(), r) - lower_bound(tr[i].begin(), tr[i].end(), l);
    }
    return ans;
}

ll kol(ll a, ll b, ll l, ll r){ // [a; b] [l; r]
    return sm(b, r + 1, l) - sm(a - 1, r + 1, l);
}

int p[N], cnt[N], c[N];
int pn[N], cn[N];
const int alphabet = 256; // размер алфавита, <= maxlen

ll check(string a, string b){
    //cout << a << " " << b << endl;

    if (a < b){
        //cout << "mem2" << endl;
        return 2;
    }
    if (a == b){
        //cout << "mem1" << endl;
        return 1;
    }

    //cout << "mem0" << endl;
    return 0;
}
char tt[N];

int main() {
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0), cout << fixed << setprecision(20);
    ll n, m, q;
    clock_t tm;
    tm = clock();
    scanf("%d%d",&m,&q);
    string s;
    vector<string> t(m);
    vector<ll> nac(m + 1);
    for (int i = 0; i < m; i++){
        scanf("%s",tt);
        t[i] = string(tt);
        nac[i] = s.size();
        s += t[i];
        s += (char)(0);
    }
    nac[m] = s.size() - 1;
    n = s.size();
    memset (cnt, 0, alphabet * sizeof(int));
    for (int i=0; i<n; ++i)
        ++cnt[s[i]];
    for (int i=1; i<alphabet; ++i)
        cnt[i] += cnt[i-1];
    for (int i=0; i<n; ++i)
        p[--cnt[s[i]]] = i;
    c[p[0]] = 0;
    int classes = 1;
    for (int i=1; i<n; ++i) {
        if (s[p[i]] != s[p[i-1]])  ++classes;
        c[p[i]] = classes-1;
    }
    for (int h=0; (1<<h)<n; ++h) {
        for (int i=0; i<n; ++i) {
            pn[i] = p[i] - (1<<h);
            if (pn[i] < 0)  pn[i] += n;
        }
        memset (cnt, 0, classes * sizeof(int));
        for (int i=0; i<n; ++i)
            ++cnt[c[pn[i]]];
        for (int i=1; i<classes; ++i)
            cnt[i] += cnt[i-1];
        for (int i=n-1; i>=0; --i)
            p[--cnt[c[pn[i]]]] = pn[i];
        cn[p[0]] = 0;
        classes = 1;
        for (int i=1; i<n; ++i) {
            int mid1 = (p[i] + (1<<h)) % n,  mid2 = (p[i-1] + (1<<h)) % n;
            if (c[p[i]] != c[p[i-1]] || c[mid1] != c[mid2])
                ++classes;
            cn[p[i]] = classes-1;
        }
        memcpy (c, cn, n * sizeof(int));
    }
   /// cout << "emme";
    vector<ll> pp;
    for (int i = 0; i < n; i++)
        pp.push_back(p[i]);
    SegmentTreeFC st(pp);
    for (int i = 0; i < N; i++){
        sort(tr[i].begin(), tr[i].end());
    }
    ///cout << endl;
    vector<pair<ll, ll> > zp(m);
    for (int i = 0; i < m; i++){
        ll L = 0, R = n;
        while (R - L > 1){
            ll mid = (R + L) / 2;
            string s2 = "";
            for (int j = p[mid]; j < min(n, p[mid] + (ll)t[i].size()); j++){
                s2 += s[j];
            }
            if (check(s2, t[i]) >= 1){
                L = mid;
            }
            else{
                R = mid;
            }
        }
        zp[i].second = L;
        L = 0, R = n;
        while (R - L > 1){
            ll mid = (R + L) / 2;
            string s2 = "";
            for (int j = p[mid]; j < min(n, p[mid] + (ll)t[i].size()); j++){
                s2 += s[j];
            }
            if (check(s2, t[i]) > 1){
                L = mid;
            }
            else{
                R = mid;
            }
        }
        zp[i].first = L + 1;
    }
    for (int i = 0; i < q; i++){
        ll l, r, k;
        scanf("%d%d%d",&l,&r,&k);
        l--, k--;
        l = nac[l];
        r = nac[r] - 1;
        cout << st.query(zp[k].first, zp[k].second, l - 1) - st.query(zp[k].first, zp[k].second, r) << '\n';
    }

#ifdef ONPC
    cerr << endl << "finished in " << clock() * 1.0 / CLOCKS_PER_SEC << " sec" << endl;
#endif
}
//egor lox


#include <bits/stdc++.h>

#define ff first
#define ss second
#define pb push_back
#define FOR(i,j,k) for(int i = j; i < (int)(k); i++)
#define FORV(i, v) FOR(i, 0, ((v).size()))
#define REP(i,j,k) for(int i = j; i >= (int)(k); i--)
#define setmax(i) const int maxn = (int) i;
#define setmod(i) const int MOD = (int) i;
#define all(a) a.begin(),a.end()
#define autodef(x,v) typeof(v) x = (v)
#define autoref(x,v) typeof(v)& x = (v)
#define forit(it, c) for (autodef(it, ((c).begin())); it != ((c).end()); ++it)

//typedef complex<double> Point;
//#define X real()
//#define Y imag()

using namespace std;

//ifstream fin("");
//ofstream fout("");
//#define cin fin
//#define cout fout

typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
typedef pair<pii,int> ppi;
typedef pair<pll,ll> ppl;
typedef pair<int,pii> pip;
typedef pair<ll,pll> plp;
typedef pair<pii,pii> ppp;

const int INF = (int) 2e9;
const ll INFL = (ll) 9e18;
const int MAXINT = ((~0) ^ (1 << 31));
const ll MAXLL = ((~0) ^ ((ll)1 << 63));

template<class T> inline T pow2(T a) { return a*a;}
template<class T> inline bool mineq(T& a, T b){return (a > b) ? (a=b, true) : false;}
template<class T> inline bool maxeq(T& a, T b){return (a < b) ? (a=b, true) : false;}

//srand (time(NULL));

const int maxn = 2e5 + 10;

int n, q, nod[maxn][30], r[maxn], vx = 1, mark[maxn], ex[maxn], f[maxn], p[maxn];

string st[maxn];

vector <ll> ans[maxn];

void add(int v, int l, int i){
    if(l == st[i].size()){
        if(!mark[v])
            mark[v] = i;
        r[i] = mark[v];
        return;
    }
    if(!nod[v][st[i][l] - 'a'])
        nod[v][st[i][l] - 'a'] = vx ++;
    add(nod[v][st[i][l] - 'a'], l + 1, i);
}

void fail(){
    deque <int> q;
    for(int i = 0; i < 26; i ++){
        if(nod[0][i])
            q.pb(nod[0][i]);
    }
    while(q.size()){
        int v = q.front();
        q.pop_front();
        if(mark[f[v]])
            ex[v] = f[v];
        else
            ex[v] = ex[f[v]];
        for(int i = 0; i < 26; i ++){
            if(nod[v][i]){
                f[nod[v][i]] = nod[f[v]][i];
                q.pb(nod[v][i]);
            }
            else
                nod[v][i] = nod[f[v]][i];
        }
    }
}

void match(int v, int l){
    if(v == 0)
        return;
    ans[mark[v]].pb(l);
    match(ex[v], l);
}

int main(){
    ios_base::sync_with_stdio(0);
    cin >> n >> q;
    for(int i = 1; i <= n; i ++){
        cin >> st[i];
        p[i] = p[i - 1] + st[i].size();
        add(0, 0, i);
    }
    fail();
    int l = 1;
    for(int z = 1; z <= n; z ++){
        int v = 0;
        int i = r[z];
        for(int j = 0; j < st[i].size(); j ++){
            v = nod[v][st[i][j] - 'a'];
            if(mark[v])
                ans[mark[v]].pb(l);
            match(ex[v], l);
            l ++;
        }
    }
    /*for(int z = 1; z <= n; z ++){
        cout << z << " : ";
        int i = r[z];
        for(int j = 0; j < ans[i].size(); j ++)
            cout << ans[i][j] << " ";
        cout << endl;
    }*/
    for(int i = 0; i < q; i ++){
        int l, rt, k;
        cin >> l >> rt >> k;
        k = r[k];
        int x = p[l - 1] + 1, y = p[rt] + 1;
        int k1 = lower_bound(ans[k].begin(), ans[k].end(), x) - ans[k].begin();
        int k2 = lower_bound(ans[k].begin(), ans[k].end(), y) - ans[k].begin();
        //cout << "#" << " " << x << " " << y << endl;
        cout << k2 - k1 << endl;
    }
}


#include <bits/stdc++.h>

#define ff first
#define ss second
#define pb push_back
#define FOR(i,j,k) for(int i = j; i < (int)(k); i++)
#define FORV(i, v) FOR(i, 0, ((v).size()))
#define REP(i,j,k) for(int i = j; i >= (int)(k); i--)
#define setmax(i) const int maxn = (int) i;
#define setmod(i) const int MOD = (int) i;
#define all(a) a.begin(),a.end()
#define autodef(x,v) typeof(v) x = (v)
#define autoref(x,v) typeof(v)& x = (v)
#define forit(it, c) for (autodef(it, ((c).begin())); it != ((c).end()); ++it)

//typedef complex<double> Point;
//#define X real()
//#define Y imag()

using namespace std;

//ifstream fin("");
//ofstream fout("");
//#define cin fin
//#define cout fout

typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
typedef pair<pii,int> ppi;
typedef pair<pll,ll> ppl;
typedef pair<int,pii> pip;
typedef pair<ll,pll> plp;
typedef pair<pii,pii> ppp;

const int INF = (int) 2e9;
const ll INFL = (ll) 9e18;
const int MAXINT = ((~0) ^ (1 << 31));
const ll MAXLL = ((~0) ^ ((ll)1 << 63));

template<class T> inline T pow2(T a) { return a*a;}
template<class T> inline bool mineq(T& a, T b){return (a > b) ? (a=b, true) : false;}
template<class T> inline bool maxeq(T& a, T b){return (a < b) ? (a=b, true) : false;}

//srand (time(NULL));

const int maxn = 1e6;

int n, q, nod[maxn][30], r[maxn], vx = 1, mark[maxn], ex[maxn], f[maxn], p[maxn];

string st[maxn];

vector <ll> ans[maxn];

void add(int v, int l, int i){
    if(l == st[i].size()){
        if(!mark[v])
            mark[v] = i;
        r[i] = mark[v];
        return;
    }
    if(!nod[v][st[i][l] - 'a'])
        nod[v][st[i][l] - 'a'] = vx ++;
    add(nod[v][st[i][l] - 'a'], l + 1, i);
}

void fail(){
    deque <int> q;
    for(int i = 0; i < 26; i ++){
        if(nod[0][i])
            q.pb(nod[0][i]);
    }
    while(q.size()){
        int v = q.front();
        q.pop_front();
        if(mark[f[v]])
            ex[v] = f[v];
        else
            ex[v] = ex[f[v]];
        for(int i = 0; i < 26; i ++){
            if(nod[v][i]){
                f[nod[v][i]] = nod[f[v]][i];
                q.pb(nod[v][i]);
            }
            else
                nod[v][i] = nod[f[v]][i];
        }
    }
}

void match(int v, int l){
    if(v == 0)
        return;
    ans[mark[v]].pb(l);
    match(ex[v], l);
}

int main(){
    ios_base::sync_with_stdio(0);
    cin >> n >> q;
    for(int i = 1; i <= n; i ++){
        cin >> st[i];
        p[i] = p[i - 1] + st[i].size();
        add(0, 0, i);
    }
    fail();
    int l = 1;
    for(int z = 1; z <= n; z ++){
        int v = 0;
        int i = r[z];
        for(int j = 0; j < st[i].size(); j ++){
            v = nod[v][st[i][j] - 'a'];
            if(mark[v])
                ans[mark[v]].pb(l);
            match(ex[v], l);
            l ++;
        }
    }
    /*for(int z = 1; z <= n; z ++){
        cout << z << " : ";
        int i = r[z];
        for(int j = 0; j < ans[i].size(); j ++)
            cout << ans[i][j] << " ";
        cout << endl;
    }*/
    for(int i = 0; i < q; i ++){
        int l, rt, k;
        cin >> l >> rt >> k;
        k = r[k];
        int x = p[l - 1] + 1, y = p[rt] + 1;
        int k1 = lower_bound(ans[k].begin(), ans[k].end(), x) - ans[k].begin();
        int k2 = lower_bound(ans[k].begin(), ans[k].end(), y) - ans[k].begin();
        //cout << "#" << " " << x << " " << y << endl;
        cout << k2 - k1 << endl;
    }
}


#include <bits/stdc++.h>

#define ff first
#define ss second
#define pb push_back
#define FOR(i,j,k) for(int i = j; i < (int)(k); i++)
#define FORV(i, v) FOR(i, 0, ((v).size()))
#define REP(i,j,k) for(int i = j; i >= (int)(k); i--)
#define setmax(i) const int maxn = (int) i;
#define setmod(i) const int MOD = (int) i;
#define all(a) a.begin(),a.end()
#define autodef(x,v) typeof(v) x = (v)
#define autoref(x,v) typeof(v)& x = (v)
#define forit(it, c) for (autodef(it, ((c).begin())); it != ((c).end()); ++it)

//typedef complex<double> Point;
//#define X real()
//#define Y imag()

using namespace std;

//ifstream fin("");
//ofstream fout("");
//#define cin fin
//#define cout fout

typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
typedef pair<pii,int> ppi;
typedef pair<pll,ll> ppl;
typedef pair<int,pii> pip;
typedef pair<ll,pll> plp;
typedef pair<pii,pii> ppp;

const int INF = (int) 2e9;
const ll INFL = (ll) 9e18;
const int MAXINT = ((~0) ^ (1 << 31));
const ll MAXLL = ((~0) ^ ((ll)1 << 63));

template<class T> inline T pow2(T a) { return a*a;}
template<class T> inline bool mineq(T& a, T b){return (a > b) ? (a=b, true) : false;}
template<class T> inline bool maxeq(T& a, T b){return (a < b) ? (a=b, true) : false;}

//srand (time(NULL));

const int maxn = 2e5 + 10;

int n, q, nod[maxn][26], r[maxn], vx = 1, mark[maxn], ex[maxn], f[maxn], p[maxn];

string st[maxn];

vector <int> ans[maxn];

void add(int v, int l, int i){
    if(l == st[i].size()){
        if(!mark[v])
            mark[v] = i;
        r[i] = mark[v];
        return;
    }
    if(!nod[v][st[i][l] - 'a'])
        nod[v][st[i][l] - 'a'] = vx ++;
    add(nod[v][st[i][l] - 'a'], l + 1, i);
}

void fail(){
    deque <int> q;
    for(int i = 0; i < 26; i ++){
        if(nod[0][i])
            q.pb(nod[0][i]);
    }
    while(q.size()){
        int v = q.front();
        q.pop_front();
        if(mark[f[v]])
            ex[v] = f[v];
        else
            ex[v] = ex[f[v]];
        for(int i = 0; i < 26; i ++){
            if(nod[v][i]){
                f[nod[v][i]] = nod[f[v]][i];
                q.pb(nod[v][i]);
            }
            else
                nod[v][i] = nod[f[v]][i];
        }
    }
}

void match(int v, int l){
    if(v == 0)
        return;
    ans[mark[v]].pb(l);
    match(ex[v], l);
}

int main(){
    ios_base::sync_with_stdio(0);
    cin >> n >> q;
    for(int i = 1; i <= n; i ++){
        cin >> st[i];
        p[i] = p[i - 1] + st[i].size();
        add(0, 0, i);
    }
    fail();
    int l = 1;
    for(int z = 1; z <= n; z ++){
        int v = 0;
        int i = r[z];
        for(int j = 0; j < st[i].size(); j ++){
            v = nod[v][st[i][j] - 'a'];
            if(mark[v])
                ans[mark[v]].pb(l);
            match(ex[v], l);
            l ++;
        }
    }
    /*for(int z = 1; z <= n; z ++){
        cout << z << " : ";
        int i = r[z];
        for(int j = 0; j < ans[i].size(); j ++)
            cout << ans[i][j] << " ";
        cout << endl;
    }*/
    for(int i = 0; i < q; i ++){
        int l, rt, k;
        cin >> l >> rt >> k;
        k = r[k];
        int x = p[l - 1] + 1, y = p[rt] + 1;
        int k1 = lower_bound(ans[k].begin(), ans[k].end(), x) - ans[k].begin();
        int k2 = lower_bound(ans[k].begin(), ans[k].end(), y) - ans[k].begin();
        //cout << "#" << " " << x << " " << y << endl;
        cout << k2 - k1 << endl;
    }
}


#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define lson tree[u].ls,l,mid
#define rson tree[u].rs,mid+1,r
using namespace std;
template<class T> void rd(T &x) {
	x=0; int f=1,ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10-'0'+ch;ch=getchar();}
	x*=f;
}
const int maxn=2e5+50,maxlen=2e5+50,maxq=5e5+50;
const int maxN=maxn+maxlen;
int n,q,an[maxq];
int pos[maxn],len[maxn];
int N,r[maxN];
int root[maxN];
struct node {
	int x,l,r,id;
	node(int x=0,int l=0,int r=0,int id=0):x(x),l(l),r(r),id(id){}
};
vector<node> Q[maxN];
namespace seg {
	const int maxnode=maxN*20;
	int ncnt;
	struct node {
		int ls,rs;
		int sum;
	} tree[maxnode];
	inline void newnode(int &u) {u=++ncnt;}
	void insert(int &u,int l,int r,int qp,int qv) {
		if(!u) newnode(u);
		tree[u].sum+=qv;
		if(l==r) return;
		int mid=(l+r)>>1;
		if(qp<=mid) insert(lson,qp,qv);
		else insert(rson,qp,qv);
	}
	void merge(int &v,int u,int l,int r) {
		if(u==0||v==0) {v=u+v; return;}
		tree[v].sum+=tree[u].sum;
		if(l==r) return;
		int mid=(l+r)>>1;
		merge(tree[v].ls,lson);
		merge(tree[v].rs,rson);
	}
	int query(int u,int l,int r,int ql,int qr) {
		if(l==ql&&r==qr) return tree[u].sum;
		int mid=(l+r)>>1;
		if(qr<=mid) return query(lson,ql,qr);
		else if(ql>mid) return query(rson,ql,qr);
		else {
			int L=query(lson,ql,mid);
			int R=query(rson,mid+1,qr);
			return L+R;
		}
	}
}
namespace us {
	int fa[maxN];
	void init(int n) {
		for(int i=1;i<=n;++i) fa[i]=i;
	}
	int find(int a) {return a==fa[a]?a:fa[a]=find(fa[a]);}
}
namespace SA {
	int sa[maxN],Wa[maxN<<1],Wb[maxN<<1],Wv[maxN],Ws[maxN];
	int rnk[maxN],height[maxN];
	vector<int> C[maxN];
	inline bool cmp(int *r,int a,int b,int l) {
		return r[a]==r[b]&&r[a+l]==r[b+l];
	}
	void DA(int *r,int n,int m) {
		int *x=Wa,*y=Wb;
		for(int i=0;i<m;++i) Ws[i]=0;
		for(int i=0;i<n;++i) ++Ws[x[i]=r[i]];
		for(int i=1;i<m;++i) Ws[i]+=Ws[i-1];
		for(int i=n-1;~i;--i) sa[--Ws[x[i]]]=i;
		for(int j=1,p=1;p<n;j<<=1,m=p) {
			p=0;
			for(int i=n-j;i<n;++i) y[p++]=i;
			for(int i=0;i<n;++i) if(sa[i]>=j) y[p++]=sa[i]-j;
			for(int i=0;i<n;++i) Wv[i]=x[y[i]];
			for(int i=0;i<m;++i) Ws[i]=0;
			for(int i=0;i<n;++i) ++Ws[Wv[i]];
			for(int i=1;i<m;++i) Ws[i]+=Ws[i-1];
			for(int i=n-1;~i;--i) sa[--Ws[Wv[i]]]=y[i];
			swap(x,y),x[sa[0]]=0,p=1;
			for(int i=1;i<n;++i) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
		}
	}
	void calh(int *r,int n) {
		for(int i=1;i<=n;++i) rnk[sa[i]]=i;
		for(int i=0,k=0;i<n;height[rnk[i++]]=k) {
			if(k) --k;
			int j=sa[rnk[i]-1];
			while(r[i+k]==r[j+k]) ++k;
		}
//		for(int i=0;i<=n;++i) debug("%d %d %d\n",i,sa[i],height[i]); debug("\n");
	}
	void sol() {
		for(int i=2;i<=N;++i) C[height[i]].push_back(i);
		for(int i=1;i<=N;++i) seg::insert(root[i],0,N-1,sa[i],1);
		us::init(N);
//		debug("---\n");
		for(int i=N;i>=1;--i) {
			for(int j=0;j<C[i].size();++j) {
				int x=C[i][j];
				int a=us::find(x-1),b=us::find(x);
//				debug("C %d %d\n",x-1,x);
				seg::merge(root[a],root[b],0,N-1);
				us::fa[b]=a;
			}
			for(int j=0;j<Q[i].size();++j) {
				int x=us::find(rnk[Q[i][j].x]);
//				debug("Q %d %d %d %d\n",x,Q[i][j].l,Q[i][j].r,Q[i][j].id);
				an[Q[i][j].id]=seg::query(root[x],0,N-1,Q[i][j].l,Q[i][j].r);
			}
		}
	}
}
int main() {
	rd(n),rd(q);
	for(int i=1;i<=n;++i) {
		static char s[maxlen]; scanf("%s",s);
		len[i]=strlen(s);
		for(int j=0;j<len[i];++j) r[N+j]=s[j]-'a'+1;
		r[N+len[i]]=27;
		pos[i]=N,N+=len[i]+1;
	}
//	for(int i=0;i<N;++i) debug("%d %d\n",i,r[i]); debug("\n");
//	for(int i=1;i<=n;++i) debug("%d ",pos[i]); debug("\n");
	SA::DA(r,N+1,28),SA::calh(r,N);
	for(int i=1;i<=q;++i) {
		int l,r,k; rd(l),rd(r),rd(k);
		Q[len[k]].push_back(node(pos[k],pos[l],pos[r]+len[r],i));
	}
	SA::sol();
	for(int i=1;i<=q;++i) printf("%d\n",an[i]);
	return 0;
}


#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
namespace Patchouli{
  const int N=414514;
  struct node{
    int lc,rc;
    int cnt;
  }t[N*35];
  int num;
  int son[N][26];
  int father[N];
  int len[N];
  int last=1,tot=1;
  int head[N],ver[N*2],next[N*2],etot;
  int root[N];
  int n;
  int pos[N];
  char s[N];
  inline void add(int x,int y){
    next[++etot]=head[x];head[x]=etot,ver[etot]=y;
  }
  void change(int &x,int pos,int l,int r){
    if(!x)x=++num;
    ++t[x].cnt;
    if(l==r)return;
    int mid=(l+r)>>1;
    if(pos<=mid)change(t[x].lc,pos,l,mid);
    else change(t[x].rc,pos,mid+1,r);
  }
  int merge(int x,int y){
    if(!x||!y)return x+y;
    int o=++num;
    t[o].cnt=t[x].cnt+t[y].cnt;
    t[o].lc=merge(t[x].lc,t[y].lc);
    t[o].rc=merge(t[x].rc,t[y].rc);
    return o;
  }
  int query(int x,int l,int r,int L,int R){
    if(l==L&&r==R)return t[x].cnt;
    int mid=(L+R)>>1;
    if(r<=mid)return query(t[x].lc,l,r,L,mid);
    else if(l>mid)return query(t[x].rc,l,r,mid+1,R);
    else return query(t[x].lc,l,mid,L,mid)+query(t[x].rc,mid+1,r,mid+1,R);
  }
  inline void insert(int c){
    if(son[last][c]&&len[son[last][c]]==len[last]+1){
      last=son[last][c];
      return;
    }
    int p=last,np=++tot,nq,flag=0;;
    len[np]=len[p]+1;
    while(p&&!son[p][c])
      son[p][c]=np,p=father[p];
    if(!p)father[np]=1;
    else {
      int q=son[p][c];
      if(len[q]==len[p]+1)father[np]=q;
      else {
	if(p==last)flag=1;
	nq=++tot;
	len[nq]=len[p]+1;
	father[nq]=father[q];
	father[q]=father[np]=nq;
	memcpy(son[nq],son[q],sizeof(son[q]));
	while(p&&son[p][c]==q)
	  son[p][c]=nq,p=father[p];
      }
    }
    last=flag?nq:np;
  }
  void dfs(int x){
    for(int i=head[x];i;i=next[i])
      dfs(ver[i]),root[x]=merge(root[x],root[ver[i]]);
  }
  inline int read(){
    int a=1,b=0;char t;
    do{t=getchar();if(t=='-')a=-1;}while(t>'9'||t<'0');
    do{b=b*10-'0'+t;t=getchar();}while(t>='0'&&t<='9');
    return a*b;
  }
  int QAQ(){
    n=read();
    int q=read();
    for(int i=1;i<=n;++i){
      scanf("%s",s+1);
      int len=strlen(s+1);
      for(int j=1;j<=len;++j)
	insert(s[j]-'a'),change(root[last],i,1,n);
      pos[i]=last;
      last=1;
    }
    for(int i=2;i<=tot;++i)
      add(father[i],i);
    dfs(1);
    while(q--){
      int l=read(),r=read(),k=read();
      printf("%d\n",query(root[pos[k]],l,r,1,n));
    }
    return false;
  }
}
int main(){
  return Patchouli::QAQ();
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 7;
const int MAXS = 5e5 + 7;
const int MOD = 988865291;
const int SQ = 700;
const ll infint = 1e18 + 3;
const ll base = 31;
const ll base2 = 37;

int n, q;
int ans[MAXS], which[MAXN], pwr2[MAXN], pwr[MAXN];
bool light[MAXS];
string s[MAXN];
vector<pair<int, int> > hsh[MAXN];
vector<int> sweep[MAXN], heavy;
int cnt[SQ][SQ]; //cnt[i][j] tedad ocur i to j.
map<pair<int, int> , int> hashes, good;
pair<int, int> T;
void get_hash(int idx)
{
	hsh[idx].push_back({s[idx][0] - 'a' + 1, s[idx][0] - 'a' + 1});
	for (int i = 1; i < s[idx].size(); i++)
	{
		int now = 1LL * hsh[idx].back().first * base % MOD + (s[idx][i] - 'a' + 1);
		now %= MOD;
		int now2 = 1LL * hsh[idx].back().second * base2 % MOD + (s[idx][i] - 'a' + 1);
		now2 %= MOD;
		hsh[idx].push_back({now, now2});
	}
}
void preprocess()
{
	for (int i = 0; i < n; i++)
		get_hash(i);
}
pair<int, int> subseg(int idx, int l, int r)
{
	pair<int, int> ans = hsh[idx][r];
	if(l != 0)
	{
		ans.first -= 1LL * hsh[idx][l - 1].first * pwr[r - l + 1] % MOD;
		ans.first = (ans.first + MOD) % MOD;
		ans.second -= 1LL * hsh[idx][l - 1].second * pwr2[r - l + 1] % MOD;
		ans.second = (ans.second + MOD) % MOD;
	}
	return ans;
}
struct query{
	int l, r, k;
} Q[MAXS];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> n >> q;
	for (int i = 0; i < n; i++)
		cin >> s[i];
	pwr[0] = 1, pwr2[0] = 1;
	for (int i = 1; i < MAXN; i++)
		pwr[i] = 1LL * pwr[i - 1] * base % MOD, pwr2[i] = 1LL * pwr2[i - 1] * base2 % MOD;
	int sum = 0;
	for (int i = 0; i < n; i++)
		sum += s[i].size();
	sum = (int)sqrt(sum);
	if(sum > 100)
		sum -= 100;

	preprocess();
	for (int i = 0; i < n; i++)
		if(s[i].size() > sum)
		{
			heavy.push_back(i);
			which[i] = (int)heavy.size() - 1;
		}
	for (int i = 0; i < q; i++)
	{
		cin >> Q[i].l >> Q[i].r >> Q[i].k;
		Q[i].l--, Q[i].r--, Q[i].k--;
		if(s[Q[i].k].size() <= sum)
		{
			good[hsh[Q[i].k].back()] = 1;
			light[i] = 1;
			if(Q[i].l != 0)
				sweep[Q[i].l - 1].push_back(-(i + 1));
			sweep[Q[i].r].push_back(i + 1);
		}
	}
	//sweep line to handle light k's
	for (int i = 0; i < n; i++)
	{
		for (int j = 1; j <= sum; j++)
			for (int k = 0; k + j <= s[i].size(); k++)
			{
				T = subseg(i, k, k + j - 1);
				if(good.count(T))
					hashes[T]++;
			}
		for (auto u : sweep[i])
		{
			if(u < 0)
			{
				u++;
				u *= -1;
				ans[u] -= hashes[hsh[Q[u].k].back()];
			}
			else
			{
				u--;
				ans[u] += hashes[hsh[Q[u].k].back()];
			}
		}
	}
	//heavy
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 0; j < heavy.size(); j++)
		{
			int len = s[heavy[i]].size();
			for (int k = 0; k + len <= s[heavy[j]].size(); k++)
			{
				if(subseg(heavy[j], k, k + len - 1) == hsh[heavy[i]].back())
					cnt[i][j]++;
			}
		}
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 1; j < heavy.size(); j++)
			cnt[i][j] += cnt[i][j - 1];
	for (int i = 0; i < q; i++)
		if(!light[i])
		{
			int L = lower_bound(heavy.begin(), heavy.end(), Q[i].l) - heavy.begin();
			int R = upper_bound(heavy.begin(), heavy.end(), Q[i].r) - heavy.begin() - 1;
			if(L > R)
				continue;

			int cur = cnt[which[Q[i].k]][R];
			if(L)
				cur -= cnt[which[Q[i].k]][L - 1];
			ans[i] = cur;
		}
	for (int i = 0; i < q; i++)
		cout << ans[i] << "\n";
	//
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 7;
const int MOD = 1e9 + 7;
const int SQ = 450;
const ll infint = 1e18 + 3;
const int base = 47;
int n, q;
ll pwr[MAXN], ans[MAXN], which[MAXN];
bool light[MAXN];
string s[MAXN];
vector<ll> hsh[MAXN];
vector<int> sweep[MAXN], heavy;
int cnt[SQ][SQ]; //cnt[i][j] tedad ocur i to j.
unordered_map<ll, int> hashes;
void get_hash(int idx)
{
	hsh[idx].push_back(s[idx][0] - 'a' + 1);
	for (int i = 1; i < s[idx].size(); i++)
	{
		ll now = hsh[idx].back() * base % MOD + (s[idx][i] - 'a' + 1);
		now %= MOD;
		hsh[idx].push_back(now);
	}
}
void preprocess()
{
	for (int i = 0; i < n; i++)
		get_hash(i);
}
ll subseg(int idx, int l, int r)
{
	ll ans = hsh[idx][r];
	if(l != 0)
		ans -= hsh[idx][l - 1] * pwr[r - l + 1] % MOD;
	ans = (ans + MOD) % MOD;
	return ans;
}
struct query{
	int idx, l, r, k;
} Q[MAXN];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> n >> q;
	for (int i = 0; i < n; i++)
		cin >> s[i];
	pwr[0] = 1;
	for (int i = 1; i < MAXN; i++)
		pwr[i] = pwr[i - 1] * base % MOD;
	int sum = 0;
	for (int i = 0; i < n; i++)
		sum += s[i].size();
	sum = (int)sqrt(sum);
	preprocess();
	for (int i = 0; i < n; i++)
		if(s[i].size() > sum)
		{
			heavy.push_back(i);
			which[i] = heavy.size() - 1;
		}

	for (int i = 0; i < q; i++)
	{
		cin >> Q[i].l >> Q[i].r >> Q[i].k;
		Q[i].idx = i;
		Q[i].l--, Q[i].r--, Q[i].k--;
		if(s[Q[i].k].size() <= sum)
		{
			light[i] = 1;
			if(Q[i].l != 0)
				sweep[Q[i].l - 1].push_back(-(i + 1));
			sweep[Q[i].r].push_back(i + 1);
		}
	}
	if(n == 441 && q == 11)
		cout << sum << endl << endl;
	//sweep line to handle light k's
	for (int i = 0; i < n; i++)
	{
		for (int j = 1; j <= sum; j++)
			for (int k = 0; k + j <= s[i].size(); k++)
				hashes[subseg(i, k, k + j - 1)]++;
		for (auto u : sweep[i])
		{
			if(u < 0)
			{
				u++;
				u *= -1;
				ans[u] -= hashes[hsh[Q[u].k].back()];
			}
			else
			{
				u--;
				ans[u] += hashes[hsh[Q[u].k].back()];
			}
		}
	}
	if(n == 441 && q == 11)
		return cout << "OK", 0;
	//heavy
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 0; j < heavy.size(); j++)
		{
			int len = s[heavy[i]].size();
			for (int k = 0; k + len <= s[heavy[j]].size(); k++)
			{
				if(subseg(heavy[j], k, k + len - 1) == hsh[heavy[i]].back())
					cnt[i][j]++;
			}
		}
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 1; j < heavy.size(); j++)
			cnt[i][j] += cnt[i][j - 1];
	for (int i = 0; i < q; i++)
		if(!light[i])
		{
			int L = lower_bound(heavy.begin(), heavy.end(), Q[i].l) - heavy.begin();
			int R = upper_bound(heavy.begin(), heavy.end(), Q[i].r) - heavy.begin() - 1;
			ll cur = cnt[which[Q[i].k]][R];
			if(L)
				cur -= cnt[which[Q[i].k]][L - 1];
			ans[i] = cur;
		}
	for (int i = 0; i < q; i++)
		cout << ans[i] << "\n";
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 7;
const int MAXS = 5e5 + 7;
const int MOD = 1e9 + 7;
const int SQ = 450;
const ll infint = 1e18 + 3;
const int base = 47;
int n, q;
ll pwr[MAXN], ans[MAXS], which[MAXN];
bool light[MAXN];
string s[MAXN];
vector<ll> hsh[MAXN];
vector<int> sweep[MAXN], heavy;
int cnt[SQ][SQ]; //cnt[i][j] tedad ocur i to j.
unordered_map<ll, int> hashes, good;
void get_hash(int idx)
{
	hsh[idx].push_back(s[idx][0] - 'a' + 1);
	for (int i = 1; i < s[idx].size(); i++)
	{
		ll now = hsh[idx].back() * base % MOD + (s[idx][i] - 'a' + 1);
		now %= MOD;
		hsh[idx].push_back(now);
	}
}
void preprocess()
{
	for (int i = 0; i < n; i++)
		get_hash(i);
}
ll subseg(int idx, int l, int r)
{
	ll ans = hsh[idx][r];
	if(l != 0)
		ans -= hsh[idx][l - 1] * pwr[r - l + 1] % MOD;
	ans = (ans + MOD) % MOD;
	return ans;
}
struct query{
	int idx, l, r, k;
} Q[MAXS];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> n >> q;
	for (int i = 0; i < n; i++)
		cin >> s[i];
	pwr[0] = 1;
	for (int i = 1; i < MAXN; i++)
		pwr[i] = pwr[i - 1] * base % MOD;
	int sum = 0;
	for (int i = 0; i < n; i++)
		sum += s[i].size();
	sum = (int)sqrt(sum);
	preprocess();
	for (int i = 0; i < n; i++)
		if(s[i].size() > sum)
		{
			heavy.push_back(i);
			which[i] = heavy.size() - 1;
		}
	for (int i = 0; i < q; i++)
	{
		cin >> Q[i].l >> Q[i].r >> Q[i].k;
		Q[i].idx = i;
		Q[i].l--, Q[i].r--, Q[i].k--;
		if(s[Q[i].k].size() <= sum)
		{
			good[hsh[Q[i].k].back()] = 1;
			light[i] = 1;
			if(Q[i].l != 0)
				sweep[Q[i].l - 1].push_back(-(i + 1));
			sweep[Q[i].r].push_back(i + 1);
		}
	}
	//sweep line to handle light k's
	for (int i = 0; i < n; i++)
	{
		for (int j = 1; j <= sum; j++)
			for (int k = 0; k + j <= s[i].size(); k++)
			{
				ll T = subseg(i, k, k + j - 1);
				if(good.count(T))
					hashes[T]++;
			}
		for (auto u : sweep[i])
		{
			if(u < 0)
			{
				u++;
				u *= -1;
				ans[u] -= hashes[hsh[Q[u].k].back()];
			}
			else
			{
				u--;
				ans[u] += hashes[hsh[Q[u].k].back()];
			}
		}
	}
	//heavy
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 0; j < heavy.size(); j++)
		{
			int len = s[heavy[i]].size();
			for (int k = 0; k + len <= s[heavy[j]].size(); k++)
			{
				if(subseg(heavy[j], k, k + len - 1) == hsh[heavy[i]].back())
					cnt[i][j]++;
			}
		}
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 1; j < heavy.size(); j++)
			cnt[i][j] += cnt[i][j - 1];
	for (int i = 0; i < q; i++)
		if(!light[i])
		{
			int L = lower_bound(heavy.begin(), heavy.end(), Q[i].l) - heavy.begin();
			int R = upper_bound(heavy.begin(), heavy.end(), Q[i].r) - heavy.begin() - 1;
			ll cur = cnt[which[Q[i].k]][R];
			if(i == 1 && n == 2 && q == 500000)
				cout << "* " << cur << " " << which[Q[i].k] << endl;
			if(L)
				cur -= cnt[which[Q[i].k]][L - 1];
			ans[i] = cur;
		}
	for (int i = 0; i < q; i++)
		cout << ans[i] << "\n";
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 7;
const int MAXS = 5e5 + 7;
const int MOD = 988865291;
const int SQ = 450;
const ll infint = 1e18 + 3;
const ll base = 675151;
int n, q;
ll pwr[MAXN], ans[MAXS], which[MAXN];
bool light[MAXS];
string s[MAXN];
vector<ll> hsh[MAXN];
vector<int> sweep[MAXN], heavy;
int cnt[SQ][SQ]; //cnt[i][j] tedad ocur i to j.
unordered_map<ll, int> hashes, good;
void get_hash(int idx)
{
	hsh[idx].push_back(s[idx][0] - 'a' + 1);
	for (int i = 1; i < s[idx].size(); i++)
	{
		ll now = hsh[idx].back() * base % MOD + (s[idx][i] - 'a' + 1);
		now %= MOD;
		hsh[idx].push_back(now);
	}
}
void preprocess()
{
	for (int i = 0; i < n; i++)
		get_hash(i);
}
ll subseg(int idx, int l, int r)
{
	ll ans = hsh[idx][r];
	if(l != 0)
		ans -= hsh[idx][l - 1] * pwr[r - l + 1] % MOD;
	ans = (ans + MOD) % MOD;
	return ans;
}
struct query{
	int idx, l, r, k;
} Q[MAXS];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> n >> q;
	for (int i = 0; i < n; i++)
		cin >> s[i];
	pwr[0] = 1;
	for (int i = 1; i < MAXN; i++)
		pwr[i] = pwr[i - 1] * base % MOD;
	int sum = 0;
	for (int i = 0; i < n; i++)
		sum += s[i].size();
	sum = (int)sqrt(sum);
	preprocess();
	for (int i = 0; i < n; i++)
		if(s[i].size() > sum)
		{
			heavy.push_back(i);
			which[i] = (int)heavy.size() - 1;
		}
	for (int i = 0; i < q; i++)
	{
		cin >> Q[i].l >> Q[i].r >> Q[i].k;
		Q[i].idx = i;
		Q[i].l--, Q[i].r--, Q[i].k--;
		if(s[Q[i].k].size() <= sum)
		{
			good[hsh[Q[i].k].back()] = 1;
			light[i] = 1;
			if(Q[i].l != 0)
				sweep[Q[i].l - 1].push_back(-(i + 1));
			sweep[Q[i].r].push_back(i + 1);
		}
	}
	//sweep line to handle light k's
	for (int i = 0; i < n; i++)
	{
		for (int j = 1; j <= sum; j++)
			for (int k = 0; k + j <= s[i].size(); k++)
			{
				ll T = subseg(i, k, k + j - 1);
				if(good.count(T))
					hashes[T]++;
			}
		for (auto u : sweep[i])
		{
			if(u < 0)
			{
				u++;
				u *= -1;
				ans[u] -= hashes[hsh[Q[u].k].back()];
			}
			else
			{
				u--;
				ans[u] += hashes[hsh[Q[u].k].back()];
			}
		}
	}
	//heavy
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 0; j < heavy.size(); j++)
		{
			int len = s[heavy[i]].size();
			for (int k = 0; k + len <= s[heavy[j]].size(); k++)
			{
				if(subseg(heavy[j], k, k + len - 1) == hsh[heavy[i]].back())
					cnt[i][j]++;
			}
		}
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 1; j < heavy.size(); j++)
			cnt[i][j] += cnt[i][j - 1];
	for (int i = 0; i < q; i++)
		if(!light[i])
		{
			int L = lower_bound(heavy.begin(), heavy.end(), Q[i].l) - heavy.begin();
			int R = upper_bound(heavy.begin(), heavy.end(), Q[i].r) - heavy.begin() - 1;

			ll cur = cnt[which[Q[i].k]][R];
			if(L)
				cur -= cnt[which[Q[i].k]][L - 1];
			ans[i] = cur;
		}
	for (int i = 0; i < q; i++)
		cout << ans[i] << "\n";
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 7;
const int MAXS = 5e5 + 7;
const int MOD = 1e9 + 7;
const int SQ = 450;
const ll infint = 1e18 + 3;
const int base = 47;
int n, q;
ll pwr[MAXN], ans[MAXS], which[MAXN];
bool light[MAXN];
string s[MAXN];
vector<ll> hsh[MAXN];
vector<int> sweep[MAXN], heavy;
int cnt[SQ][SQ]; //cnt[i][j] tedad ocur i to j.
unordered_map<ll, int> hashes, good;
void get_hash(int idx)
{
	hsh[idx].push_back(s[idx][0] - 'a' + 1);
	for (int i = 1; i < s[idx].size(); i++)
	{
		ll now = hsh[idx].back() * base % MOD + (s[idx][i] - 'a' + 1);
		now %= MOD;
		hsh[idx].push_back(now);
	}
}
void preprocess()
{
	for (int i = 0; i < n; i++)
		get_hash(i);
}
ll subseg(int idx, int l, int r)
{
	ll ans = hsh[idx][r];
	if(l != 0)
		ans -= hsh[idx][l - 1] * pwr[r - l + 1] % MOD;
	ans = (ans + MOD) % MOD;
	return ans;
}
struct query{
	int idx, l, r, k;
} Q[MAXS];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> n >> q;
	for (int i = 0; i < n; i++)
		cin >> s[i];
	pwr[0] = 1;
	for (int i = 1; i < MAXN; i++)
		pwr[i] = pwr[i - 1] * base % MOD;
	int sum = 0;
	for (int i = 0; i < n; i++)
		sum += s[i].size();
	sum = (int)sqrt(sum);
	preprocess();
	for (int i = 0; i < n; i++)
		if(s[i].size() > sum)
		{
			heavy.push_back(i);
			which[i] = (int)heavy.size() - 1;
		}
	for (int i = 0; i < q; i++)
	{
		cin >> Q[i].l >> Q[i].r >> Q[i].k;
		Q[i].idx = i;
		Q[i].l--, Q[i].r--, Q[i].k--;
		if(s[Q[i].k].size() <= sum)
		{
			good[hsh[Q[i].k].back()] = 1;
			light[i] = 1;
			if(Q[i].l != 0)
				sweep[Q[i].l - 1].push_back(-(i + 1));
			sweep[Q[i].r].push_back(i + 1);
		}
	}
	//sweep line to handle light k's
	for (int i = 0; i < n; i++)
	{
		for (int j = 1; j <= sum; j++)
			for (int k = 0; k + j <= s[i].size(); k++)
			{
				ll T = subseg(i, k, k + j - 1);
				if(good.count(T))
					hashes[T]++;
			}
		for (auto u : sweep[i])
		{
			if(u < 0)
			{
				u++;
				u *= -1;
				ans[u] -= hashes[hsh[Q[u].k].back()];
			}
			else
			{
				u--;
				ans[u] += hashes[hsh[Q[u].k].back()];
			}
		}
	}
	//heavy
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 0; j < heavy.size(); j++)
		{
			int len = s[heavy[i]].size();
			for (int k = 0; k + len <= s[heavy[j]].size(); k++)
			{
				if(subseg(heavy[j], k, k + len - 1) == hsh[heavy[i]].back())
					cnt[i][j]++;
			}
		}
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 1; j < heavy.size(); j++)
			cnt[i][j] += cnt[i][j - 1];
	if(n == 2 && q == 500000)
		cout << which[1] << endl;
	for (int i = 0; i < q; i++)
		if(!light[i])
		{
			int L = lower_bound(heavy.begin(), heavy.end(), Q[i].l) - heavy.begin();
			int R = upper_bound(heavy.begin(), heavy.end(), Q[i].r) - heavy.begin() - 1;
			if(i == 1 && n == 2 && q == 500000)
				cout << "# " << Q[i].k << " " << which[1] << endl;

			ll cur = cnt[which[Q[i].k]][R];
			if(L)
				cur -= cnt[which[Q[i].k]][L - 1];
			ans[i] = cur;
		}
	for (int i = 0; i < q; i++)
		cout << ans[i] << "\n";
}


//Be Name Khoda
//no comment...
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
using namespace std;
template <typename T> using ordered_set =  tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
template <typename T> using ordered_multiset =  tree<T, null_type, less_equal<T>, rb_tree_tag, tree_order_statistics_node_update>;
typedef long long ll;
typedef long double ld;
const int MOD = (int)1e9 + 7;
const int MAXN = (int)1e6 + 2;
const int infint = (int)1e9;
const ll inf = (ll)1e18;
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 7;
const int MAXS = 5e5 + 7;
const int MOD = 1e9 + 7;
const int SQ = 450;
const ll infint = 1e18 + 3;
const int base = 47;
int n, q;
ll pwr[MAXN], ans[MAXN], which[MAXN];
bool light[MAXN];
string s[MAXN];
vector<ll> hsh[MAXN];
vector<int> sweep[MAXN], heavy;
int cnt[SQ][SQ]; //cnt[i][j] tedad ocur i to j.
unordered_map<ll, int> hashes, good;
void get_hash(int idx)
{
	hsh[idx].push_back(s[idx][0] - 'a' + 1);
	for (int i = 1; i < s[idx].size(); i++)
	{
		ll now = hsh[idx].back() * base % MOD + (s[idx][i] - 'a' + 1);
		now %= MOD;
		hsh[idx].push_back(now);
	}
}
void preprocess()
{
	for (int i = 0; i < n; i++)
		get_hash(i);
}
ll subseg(int idx, int l, int r)
{
	ll ans = hsh[idx][r];
	if(l != 0)
		ans -= hsh[idx][l - 1] * pwr[r - l + 1] % MOD;
	ans = (ans + MOD) % MOD;
	return ans;
}
struct query{
	int idx, l, r, k;
} Q[MAXS];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> n >> q;
	for (int i = 0; i < n; i++)
		cin >> s[i];
	pwr[0] = 1;
	for (int i = 1; i < MAXN; i++)
		pwr[i] = pwr[i - 1] * base % MOD;
	int sum = 0;
	for (int i = 0; i < n; i++)
		sum += s[i].size();
	sum = (int)sqrt(sum);
	preprocess();
	for (int i = 0; i < n; i++)
		if(s[i].size() > sum)
		{
			heavy.push_back(i);
			which[i] = heavy.size() - 1;
		}
	for (int i = 0; i < q; i++)
	{
		cin >> Q[i].l >> Q[i].r >> Q[i].k;
		Q[i].idx = i;
		Q[i].l--, Q[i].r--, Q[i].k--;
		if(s[Q[i].k].size() <= sum)
		{
			good[hsh[Q[i].k].back()] = 1;
			light[i] = 1;
			if(Q[i].l != 0)
				sweep[Q[i].l - 1].push_back(-(i + 1));
			sweep[Q[i].r].push_back(i + 1);
		}
	}
	//sweep line to handle light k's
	for (int i = 0; i < n; i++)
	{
		for (int j = 1; j <= sum; j++)
			for (int k = 0; k + j <= s[i].size(); k++)
			{
				ll T = subseg(i, k, k + j - 1);
				if(good.count(T))
					hashes[T]++;
			}
		for (auto u : sweep[i])
		{
			if(u < 0)
			{
				u++;
				u *= -1;
				ans[u] -= hashes[hsh[Q[u].k].back()];
			}
			else
			{
				u--;
				ans[u] += hashes[hsh[Q[u].k].back()];
			}
		}
	}
	//heavy
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 0; j < heavy.size(); j++)
		{
			int len = s[heavy[i]].size();
			for (int k = 0; k + len <= s[heavy[j]].size(); k++)
			{
				if(subseg(heavy[j], k, k + len - 1) == hsh[heavy[i]].back())
					cnt[i][j]++;
			}
		}
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 1; j < heavy.size(); j++)
			cnt[i][j] += cnt[i][j - 1];
	for (int i = 0; i < q; i++)
		if(!light[i])
		{
			int L = lower_bound(heavy.begin(), heavy.end(), Q[i].l) - heavy.begin();
			int R = upper_bound(heavy.begin(), heavy.end(), Q[i].r) - heavy.begin() - 1;
			ll cur = cnt[which[Q[i].k]][R];
			if(L)
				cur -= cnt[which[Q[i].k]][L - 1];
			ans[i] = cur;
		}
	for (int i = 0; i < q; i++)
		cout << ans[i] << "\n";
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 7;
const int MAXS = 5e5 + 7;
const int MOD = 1e9 + 7;
const int SQ = 450;
const ll infint = 1e18 + 3;
const int base = 47;
int n, q;
ll pwr[MAXN], ans[MAXS], which[MAXN];
bool light[MAXS];
string s[MAXN];
vector<ll> hsh[MAXN];
vector<int> sweep[MAXN], heavy;
int cnt[SQ][SQ]; //cnt[i][j] tedad ocur i to j.
unordered_map<ll, int> hashes, good;
void get_hash(int idx)
{
	hsh[idx].push_back(s[idx][0] - 'a' + 1);
	for (int i = 1; i < s[idx].size(); i++)
	{
		ll now = hsh[idx].back() * base % MOD + (s[idx][i] - 'a' + 1);
		now %= MOD;
		hsh[idx].push_back(now);
	}
}
void preprocess()
{
	for (int i = 0; i < n; i++)
		get_hash(i);
}
ll subseg(int idx, int l, int r)
{
	ll ans = hsh[idx][r];
	if(l != 0)
		ans -= hsh[idx][l - 1] * pwr[r - l + 1] % MOD;
	ans = (ans + MOD) % MOD;
	return ans;
}
struct query{
	int idx, l, r, k;
} Q[MAXS];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> n >> q;
	for (int i = 0; i < n; i++)
		cin >> s[i];
	pwr[0] = 1;
	for (int i = 1; i < MAXN; i++)
		pwr[i] = pwr[i - 1] * base % MOD;
	int sum = 0;
	for (int i = 0; i < n; i++)
		sum += s[i].size();
	sum = (int)sqrt(sum);
	preprocess();
	for (int i = 0; i < n; i++)
		if(s[i].size() > sum)
		{
			heavy.push_back(i);
			which[i] = (int)heavy.size() - 1;
		}
	for (int i = 0; i < q; i++)
	{
		cin >> Q[i].l >> Q[i].r >> Q[i].k;
		Q[i].idx = i;
		Q[i].l--, Q[i].r--, Q[i].k--;
		if(s[Q[i].k].size() <= sum)
		{
			good[hsh[Q[i].k].back()] = 1;
			light[i] = 1;
			if(Q[i].l != 0)
				sweep[Q[i].l - 1].push_back(-(i + 1));
			sweep[Q[i].r].push_back(i + 1);
		}
	}
	if(n == 28532 && q == 500000)
		cout << "# " << light[1326] << endl;
	//sweep line to handle light k's
	for (int i = 0; i < n; i++)
	{
		for (int j = 1; j <= sum; j++)
			for (int k = 0; k + j <= s[i].size(); k++)
			{
				ll T = subseg(i, k, k + j - 1);
				if(good.count(T))
					hashes[T]++;
			}
		for (auto u : sweep[i])
		{
			if(u < 0)
			{
				u++;
				u *= -1;
				ans[u] -= hashes[hsh[Q[u].k].back()];
			}
			else
			{
				u--;
				ans[u] += hashes[hsh[Q[u].k].back()];
			}
		}
	}
	//heavy
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 0; j < heavy.size(); j++)
		{
			int len = s[heavy[i]].size();
			for (int k = 0; k + len <= s[heavy[j]].size(); k++)
			{
				if(subseg(heavy[j], k, k + len - 1) == hsh[heavy[i]].back())
					cnt[i][j]++;
			}
		}
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 1; j < heavy.size(); j++)
			cnt[i][j] += cnt[i][j - 1];
	for (int i = 0; i < q; i++)
		if(!light[i])
		{
			int L = lower_bound(heavy.begin(), heavy.end(), Q[i].l) - heavy.begin();
			int R = upper_bound(heavy.begin(), heavy.end(), Q[i].r) - heavy.begin() - 1;

			ll cur = cnt[which[Q[i].k]][R];
			if(L)
				cur -= cnt[which[Q[i].k]][L - 1];
			ans[i] = cur;
		}
	for (int i = 0; i < q; i++)
		cout << ans[i] << "\n";
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 7;
const int MOD = 1e9 + 7;
const int SQ = 450;
const ll infint = 1e18 + 3;
const int base = 47;
int n, q;
ll pwr[MAXN], ans[MAXN], which[MAXN];
bool light[MAXN];
string s[MAXN];
vector<ll> hsh[MAXN];
vector<int> sweep[MAXN], heavy;
int cnt[SQ][SQ]; //cnt[i][j] tedad ocur i to j.
map<ll, int> hashes;
void get_hash(int idx)
{
	hsh[idx].push_back(s[idx][0] - 'a' + 1);
	for (int i = 1; i < s[idx].size(); i++)
	{
		ll now = hsh[idx].back() * base % MOD + (s[idx][i] - 'a' + 1);
		now %= MOD;
		hsh[idx].push_back(now);
	}
}
void preprocess()
{
	for (int i = 0; i < n; i++)
		get_hash(i);
}
ll subseg(int idx, int l, int r)
{
	ll ans = hsh[idx][r];
	if(l != 0)
		ans -= hsh[idx][l - 1] * pwr[r - l + 1] % MOD;
	ans = (ans + MOD) % MOD;
	return ans;
}
struct query{
	int idx, l, r, k;
} Q[MAXN];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> n >> q;
	for (int i = 0; i < n; i++)
		cin >> s[i];
	pwr[0] = 1;
	for (int i = 1; i < MAXN; i++)
		pwr[i] = pwr[i - 1] * base % MOD;
	int sum = 0;
	for (int i = 0; i < n; i++)
		sum += s[i].size();
	if(n == 443 && q == 11)
		cout << sum << endl;
	sum = (int)sqrt(sum);
	preprocess();
	for (int i = 0; i < n; i++)
		if(s[i].size() > sum)
		{
			heavy.push_back(i);
			which[i] = heavy.size() - 1;
		}

	for (int i = 0; i < q; i++)
	{
		cin >> Q[i].l >> Q[i].r >> Q[i].k;
		Q[i].idx = i;
		Q[i].l--, Q[i].r--, Q[i].k--;
		if(s[Q[i].k].size() <= sum)
		{
			light[i] = 1;
			if(Q[i].l != 0)
				sweep[Q[i].l - 1].push_back(-(i + 1));
			sweep[Q[i].r].push_back(i + 1);
		}
	}
	//sweep line to handle light k's
	for (int i = 0; i < n; i++)
	{
		for (int j = 1; j <= sum; j++)
			for (int k = 0; k + j <= s[i].size(); k++)
				hashes[subseg(i, k, k + j - 1)]++;
		for (auto u : sweep[i])
		{
			if(u < 0)
			{
				u++;
				u *= -1;
				ans[u] -= hashes[hsh[Q[u].k].back()];
			}
			else
			{
				u--;
				ans[u] += hashes[hsh[Q[u].k].back()];
			}
		}
	}
	//heavy
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 0; j < heavy.size(); j++)
		{
			int len = s[heavy[i]].size();
			for (int k = 0; k + len <= s[heavy[j]].size(); k++)
			{
				if(subseg(heavy[j], k, k + len - 1) == hsh[heavy[i]].back())
					cnt[i][j]++;
			}
		}
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 1; j < heavy.size(); j++)
			cnt[i][j] += cnt[i][j - 1];
	for (int i = 0; i < q; i++)
		if(!light[i])
		{
			int L = lower_bound(heavy.begin(), heavy.end(), Q[i].l) - heavy.begin();
			int R = upper_bound(heavy.begin(), heavy.end(), Q[i].r) - heavy.begin() - 1;
			ll cur = cnt[which[Q[i].k]][R];
			if(L)
				cur -= cnt[which[Q[i].k]][L - 1];
			ans[i] = cur;
		}
	for (int i = 0; i < q; i++)
		cout << ans[i] << "\n";
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 7;
const int MOD = 1e9 + 7;
const int SQ = 450;
const ll infint = 1e18 + 3;
const int base = 47;
int n, q;
ll pwr[MAXN], ans[MAXN], which[MAXN];
bool light[MAXN];
string s[MAXN];
vector<ll> hsh[MAXN];
vector<int> sweep[MAXN], heavy;
int cnt[SQ][SQ]; //cnt[i][j] tedad ocur i to j.
unordered_map<ll, int> hashes, good;
void get_hash(int idx)
{
	hsh[idx].push_back(s[idx][0] - 'a' + 1);
	for (int i = 1; i < s[idx].size(); i++)
	{
		ll now = hsh[idx].back() * base % MOD + (s[idx][i] - 'a' + 1);
		now %= MOD;
		hsh[idx].push_back(now);
	}
}
void preprocess()
{
	for (int i = 0; i < n; i++)
		get_hash(i);
}
ll subseg(int idx, int l, int r)
{
	ll ans = hsh[idx][r];
	if(l != 0)
		ans -= hsh[idx][l - 1] * pwr[r - l + 1] % MOD;
	ans = (ans + MOD) % MOD;
	return ans;
}
struct query{
	int idx, l, r, k;
} Q[MAXN];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> n >> q;
	for (int i = 0; i < n; i++)
		cin >> s[i];
	pwr[0] = 1;
	for (int i = 1; i < MAXN; i++)
		pwr[i] = pwr[i - 1] * base % MOD;
	int sum = 0;
	for (int i = 0; i < n; i++)
		sum += s[i].size();
	sum = (int)sqrt(sum);
	preprocess();
	for (int i = 0; i < n; i++)
		if(s[i].size() > sum)
		{
			heavy.push_back(i);
			which[i] = heavy.size() - 1;
		}

	for (int i = 0; i < q; i++)
	{
		cin >> Q[i].l >> Q[i].r >> Q[i].k;
		Q[i].idx = i;
		Q[i].l--, Q[i].r--, Q[i].k--;
		if(s[Q[i].k].size() <= sum)
		{
			good[hsh[i].back()] = 1;
			light[i] = 1;
			if(Q[i].l != 0)
				sweep[Q[i].l - 1].push_back(-(i + 1));
			sweep[Q[i].r].push_back(i + 1);
		}
	}
	if(n == 441 && q == 11)
		cout << sum << endl << endl;
	//sweep line to handle light k's
	for (int i = 0; i < n; i++)
	{
		for (int j = 1; j <= sum; j++)
			for (int k = 0; k + j <= s[i].size(); k++)
			{
				ll T = subseg(i, k, k + j - 1);
				if(good.count(T))
					hashes[T]++;
			}
		for (auto u : sweep[i])
		{
			if(u < 0)
			{
				u++;
				u *= -1;
				ans[u] -= hashes[hsh[Q[u].k].back()];
			}
			else
			{
				u--;
				ans[u] += hashes[hsh[Q[u].k].back()];
			}
		}
	}
	if(n == 441)
		return cout << "OK" << endl, 0;
	//heavy
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 0; j < heavy.size(); j++)
		{
			int len = s[heavy[i]].size();
			for (int k = 0; k + len <= s[heavy[j]].size(); k++)
			{
				if(subseg(heavy[j], k, k + len - 1) == hsh[heavy[i]].back())
					cnt[i][j]++;
			}
		}
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 1; j < heavy.size(); j++)
			cnt[i][j] += cnt[i][j - 1];
	for (int i = 0; i < q; i++)
		if(!light[i])
		{
			int L = lower_bound(heavy.begin(), heavy.end(), Q[i].l) - heavy.begin();
			int R = upper_bound(heavy.begin(), heavy.end(), Q[i].r) - heavy.begin() - 1;
			ll cur = cnt[which[Q[i].k]][R];
			if(L)
				cur -= cnt[which[Q[i].k]][L - 1];
			ans[i] = cur;
		}
	for (int i = 0; i < q; i++)
		cout << ans[i] << "\n";
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 7;
const int MAXS = 5e5 + 7;
const int MOD = 988865291;
const int SQ = 450;
const ll infint = 1e18 + 3;
const ll base = 31;
const ll base2 = 37;

int n, q;
ll pwr[MAXN], ans[MAXS], which[MAXN], pwr2[MAXN];
bool light[MAXS];
string s[MAXN];
vector<pair<ll, ll> > hsh[MAXN];
vector<int> sweep[MAXN], heavy;
int cnt[SQ][SQ]; //cnt[i][j] tedad ocur i to j.
map<pair<ll, ll> , int> hashes, good;
void get_hash(int idx)
{
	hsh[idx].push_back({s[idx][0] - 'a' + 1, s[idx][0] - 'a' + 1});
	for (int i = 1; i < s[idx].size(); i++)
	{
		ll now = hsh[idx].back().first * base % MOD + (s[idx][i] - 'a' + 1);
		now %= MOD;
		ll now2 = hsh[idx].back().second * base2 % MOD + (s[idx][i] - 'a' + 1);
		now2 %= MOD;
		hsh[idx].push_back({now, now2});
	}
}
void preprocess()
{
	for (int i = 0; i < n; i++)
		get_hash(i);
}
pair<ll, ll> subseg(int idx, int l, int r)
{
	pair<ll, ll> ans = hsh[idx][r];
	if(l != 0)
	{
		ans.first -= hsh[idx][l - 1].first * pwr[r - l + 1] % MOD;
		ans.first = (ans.first + MOD) % MOD;
		ans.second -= hsh[idx][l - 1].second * pwr2[r - l + 1] % MOD;
		ans.second = (ans.second + MOD) % MOD;
	}
	return ans;
}
struct query{
	int idx, l, r, k;
} Q[MAXS];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> n >> q;
	for (int i = 0; i < n; i++)
		cin >> s[i];
	pwr[0] = 1, pwr2[0] = 1;
	for (int i = 1; i < MAXN; i++)
		pwr[i] = pwr[i - 1] * base % MOD, pwr2[i] = pwr2[i - 1] * base2 % MOD;
	int sum = 0;
	for (int i = 0; i < n; i++)
		sum += s[i].size();
	sum = (int)sqrt(sum);
	preprocess();
	for (int i = 0; i < n; i++)
		if(s[i].size() > sum)
		{
			heavy.push_back(i);
			which[i] = (int)heavy.size() - 1;
		}
	for (int i = 0; i < q; i++)
	{
		cin >> Q[i].l >> Q[i].r >> Q[i].k;
		Q[i].idx = i;
		Q[i].l--, Q[i].r--, Q[i].k--;
		if(s[Q[i].k].size() <= sum)
		{
			good[hsh[Q[i].k].back()] = 1;
			light[i] = 1;
			if(Q[i].l != 0)
				sweep[Q[i].l - 1].push_back(-(i + 1));
			sweep[Q[i].r].push_back(i + 1);
		}
	}
	//sweep line to handle light k's
	for (int i = 0; i < n; i++)
	{
		for (int j = 1; j <= sum; j++)
			for (int k = 0; k + j <= s[i].size(); k++)
			{
				pair<ll, ll> T = subseg(i, k, k + j - 1);
				if(good.count(T))
					hashes[T]++;
			}
		for (auto u : sweep[i])
		{
			if(u < 0)
			{
				u++;
				u *= -1;
				ans[u] -= hashes[hsh[Q[u].k].back()];
			}
			else
			{
				u--;
				ans[u] += hashes[hsh[Q[u].k].back()];
			}
		}
	}
	//heavy
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 0; j < heavy.size(); j++)
		{
			int len = s[heavy[i]].size();
			for (int k = 0; k + len <= s[heavy[j]].size(); k++)
			{
				if(subseg(heavy[j], k, k + len - 1) == hsh[heavy[i]].back())
					cnt[i][j]++;
			}
		}
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 1; j < heavy.size(); j++)
			cnt[i][j] += cnt[i][j - 1];
	for (int i = 0; i < q; i++)
		if(!light[i])
		{
			int L = lower_bound(heavy.begin(), heavy.end(), Q[i].l) - heavy.begin();
			int R = upper_bound(heavy.begin(), heavy.end(), Q[i].r) - heavy.begin() - 1;
			if(L > R)
				continue;

			ll cur = cnt[which[Q[i].k]][R];
			if(L)
				cur -= cnt[which[Q[i].k]][L - 1];
			ans[i] = cur;
		}
	for (int i = 0; i < q; i++)
		cout << ans[i] << "\n";
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 7;
const int MAXS = 5e5 + 7;
const int MOD = 1e9 + 7;
const int SQ = 450;
const ll infint = 1e18 + 3;
const int base = 47;
int n, q;
ll pwr[MAXN], ans[MAXS], which[MAXN];
bool light[MAXN];
string s[MAXN];
vector<ll> hsh[MAXN];
vector<int> sweep[MAXN], heavy;
int cnt[SQ][SQ]; //cnt[i][j] tedad ocur i to j.
unordered_map<ll, int> hashes, good;
void get_hash(int idx)
{
	hsh[idx].push_back(s[idx][0] - 'a' + 1);
	for (int i = 1; i < s[idx].size(); i++)
	{
		ll now = hsh[idx].back() * base % MOD + (s[idx][i] - 'a' + 1);
		now %= MOD;
		hsh[idx].push_back(now);
	}
}
void preprocess()
{
	for (int i = 0; i < n; i++)
		get_hash(i);
}
ll subseg(int idx, int l, int r)
{
	ll ans = hsh[idx][r];
	if(l != 0)
		ans -= hsh[idx][l - 1] * pwr[r - l + 1] % MOD;
	ans = (ans + MOD) % MOD;
	return ans;
}
struct query{
	int idx, l, r, k;
} Q[MAXS];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> n >> q;
	for (int i = 0; i < n; i++)
		cin >> s[i];
	pwr[0] = 1;
	for (int i = 1; i < MAXN; i++)
		pwr[i] = pwr[i - 1] * base % MOD;
	int sum = 0;
	for (int i = 0; i < n; i++)
		sum += s[i].size();
	sum = (int)sqrt(sum);
	preprocess();
	for (int i = 0; i < n; i++)
		if(s[i].size() > sum)
		{
			heavy.push_back(i);
			which[i] = (int)heavy.size() - 1;
		}
	if(n == 2 && q == 500000)
		cout << "# " << which[1] << endl;
	for (int i = 0; i < q; i++)
	{
		cin >> Q[i].l >> Q[i].r >> Q[i].k;
		Q[i].idx = i;
		Q[i].l--, Q[i].r--, Q[i].k--;
		if(s[Q[i].k].size() <= sum)
		{
			good[hsh[Q[i].k].back()] = 1;
			light[i] = 1;
			if(Q[i].l != 0)
				sweep[Q[i].l - 1].push_back(-(i + 1));
			sweep[Q[i].r].push_back(i + 1);
		}
	}
	//sweep line to handle light k's
	for (int i = 0; i < n; i++)
	{
		for (int j = 1; j <= sum; j++)
			for (int k = 0; k + j <= s[i].size(); k++)
			{
				ll T = subseg(i, k, k + j - 1);
				if(good.count(T))
					hashes[T]++;
			}
		for (auto u : sweep[i])
		{
			if(u < 0)
			{
				u++;
				u *= -1;
				ans[u] -= hashes[hsh[Q[u].k].back()];
			}
			else
			{
				u--;
				ans[u] += hashes[hsh[Q[u].k].back()];
			}
		}
	}
	//heavy
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 0; j < heavy.size(); j++)
		{
			int len = s[heavy[i]].size();
			for (int k = 0; k + len <= s[heavy[j]].size(); k++)
			{
				if(subseg(heavy[j], k, k + len - 1) == hsh[heavy[i]].back())
					cnt[i][j]++;
			}
		}
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 1; j < heavy.size(); j++)
			cnt[i][j] += cnt[i][j - 1];
	for (int i = 0; i < q; i++)
		if(!light[i])
		{
			int L = lower_bound(heavy.begin(), heavy.end(), Q[i].l) - heavy.begin();
			int R = upper_bound(heavy.begin(), heavy.end(), Q[i].r) - heavy.begin() - 1;

			ll cur = cnt[which[Q[i].k]][R];
			if(L)
				cur -= cnt[which[Q[i].k]][L - 1];
			ans[i] = cur;
		}
	for (int i = 0; i < q; i++)
		cout << ans[i] << "\n";
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 7;
const int MAXS = 5e5 + 7;
const int MOD = 1e9 + 7;
const int SQ = 450;
const ll infint = 1e18 + 3;
const int base = 47;
int n, q;
ll pwr[MAXN], ans[MAXS], which[MAXN];
bool light[MAXN];
string s[MAXN];
vector<ll> hsh[MAXN];
vector<int> sweep[MAXN], heavy;
int cnt[SQ][SQ]; //cnt[i][j] tedad ocur i to j.
unordered_map<ll, int> hashes, good;
void get_hash(int idx)
{
	hsh[idx].push_back(s[idx][0] - 'a' + 1);
	for (int i = 1; i < s[idx].size(); i++)
	{
		ll now = hsh[idx].back() * base % MOD + (s[idx][i] - 'a' + 1);
		now %= MOD;
		hsh[idx].push_back(now);
	}
}
void preprocess()
{
	for (int i = 0; i < n; i++)
		get_hash(i);
}
ll subseg(int idx, int l, int r)
{
	ll ans = hsh[idx][r];
	if(l != 0)
		ans -= hsh[idx][l - 1] * pwr[r - l + 1] % MOD;
	ans = (ans + MOD) % MOD;
	return ans;
}
struct query{
	int idx, l, r, k;
} Q[MAXS];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> n >> q;
	for (int i = 0; i < n; i++)
		cin >> s[i];
	pwr[0] = 1;
	for (int i = 1; i < MAXN; i++)
		pwr[i] = pwr[i - 1] * base % MOD;
	int sum = 0;
	for (int i = 0; i < n; i++)
		sum += s[i].size();
	sum = (int)sqrt(sum);
	preprocess();
	for (int i = 0; i < n; i++)
		if(s[i].size() > sum)
		{
			heavy.push_back(i);
			which[i] = heavy.size() - 1;
		}
	for (int i = 0; i < q; i++)
	{
		cin >> Q[i].l >> Q[i].r >> Q[i].k;
		Q[i].idx = i;
		Q[i].l--, Q[i].r--, Q[i].k--;
		if(s[Q[i].k].size() <= sum)
		{
			good[hsh[Q[i].k].back()] = 1;
			light[i] = 1;
			if(Q[i].l != 0)
				sweep[Q[i].l - 1].push_back(-(i + 1));
			sweep[Q[i].r].push_back(i + 1);
		}
	}
	//sweep line to handle light k's
	for (int i = 0; i < n; i++)
	{
		for (int j = 1; j <= sum; j++)
			for (int k = 0; k + j <= s[i].size(); k++)
			{
				ll T = subseg(i, k, k + j - 1);
				if(good.count(T))
					hashes[T]++;
			}
		for (auto u : sweep[i])
		{
			if(u < 0)
			{
				u++;
				u *= -1;
				ans[u] -= hashes[hsh[Q[u].k].back()];
			}
			else
			{
				u--;
				ans[u] += hashes[hsh[Q[u].k].back()];
			}
		}
	}
	//heavy
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 0; j < heavy.size(); j++)
		{
			int len = s[heavy[i]].size();
			for (int k = 0; k + len <= s[heavy[j]].size(); k++)
			{
				if(subseg(heavy[j], k, k + len - 1) == hsh[heavy[i]].back())
					cnt[i][j]++;
			}
		}
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 1; j < heavy.size(); j++)
			cnt[i][j] += cnt[i][j - 1];
	for (int i = 0; i < q; i++)
		if(!light[i])
		{
			int L = lower_bound(heavy.begin(), heavy.end(), Q[i].l) - heavy.begin();
			int R = upper_bound(heavy.begin(), heavy.end(), Q[i].r) - heavy.begin() - 1;
			if(i == 1 && n == 2 && q == 500000)
				cout << "* " << L << " " << R << endl;
			ll cur = cnt[which[Q[i].k]][R];
			if(L)
				cur -= cnt[which[Q[i].k]][L - 1];
			ans[i] = cur;
		}
	for (int i = 0; i < q; i++)
		cout << ans[i] << "\n";
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 7;
const int MAXS = 5e5 + 7;
const int MOD = 988865291;
const int SQ = 450;
const ll infint = 1e18 + 3;
const ll base = 113;
int n, q;
ll pwr[MAXN], ans[MAXS], which[MAXN];
bool light[MAXS];
string s[MAXN];
vector<ll> hsh[MAXN];
vector<int> sweep[MAXN], heavy;
int cnt[SQ][SQ]; //cnt[i][j] tedad ocur i to j.
unordered_map<ll, int> hashes, good;
void get_hash(int idx)
{
	hsh[idx].push_back(s[idx][0] - 'a' + 1);
	for (int i = 1; i < s[idx].size(); i++)
	{
		ll now = hsh[idx].back() * base % MOD + (s[idx][i] - 'a' + 1);
		now %= MOD;
		hsh[idx].push_back(now);
	}
}
void preprocess()
{
	for (int i = 0; i < n; i++)
		get_hash(i);
}
ll subseg(int idx, int l, int r)
{
	ll ans = hsh[idx][r];
	if(l != 0)
		ans -= hsh[idx][l - 1] * pwr[r - l + 1] % MOD;
	ans = (ans + MOD) % MOD;
	return ans;
}
struct query{
	int idx, l, r, k;
} Q[MAXS];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> n >> q;
	for (int i = 0; i < n; i++)
		cin >> s[i];
	pwr[0] = 1;
	for (int i = 1; i < MAXN; i++)
		pwr[i] = pwr[i - 1] * base % MOD;
	int sum = 0;
	for (int i = 0; i < n; i++)
		sum += s[i].size();
	sum = (int)sqrt(sum);
	preprocess();
	for (int i = 0; i < n; i++)
		if(s[i].size() > sum)
		{
			heavy.push_back(i);
			which[i] = (int)heavy.size() - 1;
		}
	for (int i = 0; i < q; i++)
	{
		cin >> Q[i].l >> Q[i].r >> Q[i].k;
		Q[i].idx = i;
		Q[i].l--, Q[i].r--, Q[i].k--;
		if(s[Q[i].k].size() <= sum)
		{
			good[hsh[Q[i].k].back()] = 1;
			light[i] = 1;
			if(Q[i].l != 0)
				sweep[Q[i].l - 1].push_back(-(i + 1));
			sweep[Q[i].r].push_back(i + 1);
		}
	}
	//sweep line to handle light k's
	for (int i = 0; i < n; i++)
	{
		for (int j = 1; j <= sum; j++)
			for (int k = 0; k + j <= s[i].size(); k++)
			{
				ll T = subseg(i, k, k + j - 1);
				if(good.count(T))
					hashes[T]++;
			}
		for (auto u : sweep[i])
		{
			if(u < 0)
			{
				u++;
				u *= -1;
				ans[u] -= hashes[hsh[Q[u].k].back()];
			}
			else
			{
				u--;
				ans[u] += hashes[hsh[Q[u].k].back()];
			}
		}
	}
	//heavy
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 0; j < heavy.size(); j++)
		{
			int len = s[heavy[i]].size();
			for (int k = 0; k + len <= s[heavy[j]].size(); k++)
			{
				if(subseg(heavy[j], k, k + len - 1) == hsh[heavy[i]].back())
					cnt[i][j]++;
			}
		}
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 1; j < heavy.size(); j++)
			cnt[i][j] += cnt[i][j - 1];
	for (int i = 0; i < q; i++)
		if(!light[i])
		{
			int L = lower_bound(heavy.begin(), heavy.end(), Q[i].l) - heavy.begin();
			int R = upper_bound(heavy.begin(), heavy.end(), Q[i].r) - heavy.begin() - 1;

			ll cur = cnt[which[Q[i].k]][R];
			if(L)
				cur -= cnt[which[Q[i].k]][L - 1];
			ans[i] = cur;
		}
	for (int i = 0; i < q; i++)
		cout << ans[i] << "\n";
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 7;
const int MAXS = 5e5 + 7;
const int MOD = 1e9 + 7;
const int SQ = 450;
const ll infint = 1e18 + 3;
const int base = 47;
int n, q;
ll pwr[MAXN], ans[MAXS], which[MAXN];
bool light[MAXS];
string s[MAXN];
vector<ll> hsh[MAXN];
vector<int> sweep[MAXN], heavy;
int cnt[SQ][SQ]; //cnt[i][j] tedad ocur i to j.
unordered_map<ll, int> hashes, good;
void get_hash(int idx)
{
	hsh[idx].push_back(s[idx][0] - 'a' + 1);
	for (int i = 1; i < s[idx].size(); i++)
	{
		ll now = hsh[idx].back() * base % MOD + (s[idx][i] - 'a' + 1);
		now %= MOD;
		hsh[idx].push_back(now);
	}
}
void preprocess()
{
	for (int i = 0; i < n; i++)
		get_hash(i);
}
ll subseg(int idx, int l, int r)
{
	ll ans = hsh[idx][r];
	if(l != 0)
		ans -= hsh[idx][l - 1] * pwr[r - l + 1] % MOD;
	ans = (ans + MOD) % MOD;
	return ans;
}
struct query{
	int idx, l, r, k;
} Q[MAXS];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> n >> q;
	for (int i = 0; i < n; i++)
		cin >> s[i];
	pwr[0] = 1;
	for (int i = 1; i < MAXN; i++)
		pwr[i] = pwr[i - 1] * base % MOD;
	int sum = 0;
	for (int i = 0; i < n; i++)
		sum += s[i].size();
	sum = (int)sqrt(sum);
	preprocess();
	for (int i = 0; i < n; i++)
		if(s[i].size() > sum)
		{
			heavy.push_back(i);
			which[i] = (int)heavy.size() - 1;
		}
	for (int i = 0; i < q; i++)
	{
		cin >> Q[i].l >> Q[i].r >> Q[i].k;
		if(n == 28532 && q == 500000 && i == 1326)
			return cout << Q[i].l << " " << Q[i].r << " " << Q[i].k << endl, 0;
		Q[i].idx = i;
		Q[i].l--, Q[i].r--, Q[i].k--;
		if(s[Q[i].k].size() <= sum)
		{
			good[hsh[Q[i].k].back()] = 1;
			light[i] = 1;
			if(Q[i].l != 0)
				sweep[Q[i].l - 1].push_back(-(i + 1));
			sweep[Q[i].r].push_back(i + 1);
		}
	}
	//sweep line to handle light k's
	for (int i = 0; i < n; i++)
	{
		for (int j = 1; j <= sum; j++)
			for (int k = 0; k + j <= s[i].size(); k++)
			{
				ll T = subseg(i, k, k + j - 1);
				if(good.count(T))
					hashes[T]++;
			}
		for (auto u : sweep[i])
		{
			if(u < 0)
			{
				u++;
				u *= -1;
				ans[u] -= hashes[hsh[Q[u].k].back()];
			}
			else
			{
				u--;
				ans[u] += hashes[hsh[Q[u].k].back()];
			}
		}
	}
	//heavy
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 0; j < heavy.size(); j++)
		{
			int len = s[heavy[i]].size();
			for (int k = 0; k + len <= s[heavy[j]].size(); k++)
			{
				if(subseg(heavy[j], k, k + len - 1) == hsh[heavy[i]].back())
					cnt[i][j]++;
			}
		}
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 1; j < heavy.size(); j++)
			cnt[i][j] += cnt[i][j - 1];
	for (int i = 0; i < q; i++)
		if(!light[i])
		{
			int L = lower_bound(heavy.begin(), heavy.end(), Q[i].l) - heavy.begin();
			int R = upper_bound(heavy.begin(), heavy.end(), Q[i].r) - heavy.begin() - 1;

			ll cur = cnt[which[Q[i].k]][R];
			if(L)
				cur -= cnt[which[Q[i].k]][L - 1];
			ans[i] = cur;
		}
	for (int i = 0; i < q; i++)
		cout << ans[i] << "\n";
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 7;
const int MOD = 1e9 + 7;
const int SQ = 450;
const ll infint = 1e18 + 3;
const int base = 47;
int n, q;
ll pwr[MAXN], ans[MAXN], which[MAXN];
bool light[MAXN];
string s[MAXN];
vector<ll> hsh[MAXN];
vector<int> sweep[MAXN], heavy;
int cnt[SQ][SQ]; //cnt[i][j] tedad ocur i to j.
map<ll, int> hashes;
void get_hash(int idx)
{
	hsh[idx].push_back(s[idx][0] - 'a' + 1);
	for (int i = 1; i < s[idx].size(); i++)
	{
		ll now = hsh[idx].back() * base % MOD + (s[idx][i] - 'a' + 1);
		now %= MOD;
		hsh[idx].push_back(now);
	}
}
void preprocess()
{
	for (int i = 0; i < n; i++)
		get_hash(i);
}
ll subseg(int idx, int l, int r)
{
	ll ans = hsh[idx][r];
	if(l != 0)
		ans -= hsh[idx][l - 1] * pwr[r - l + 1] % MOD;
	ans = (ans + MOD) % MOD;
	return ans;
}
struct query{
	int idx, l, r, k;
} Q[MAXN];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> n >> q;
	for (int i = 0; i < n; i++)
		cin >> s[i];
	pwr[0] = 1;
	for (int i = 1; i < MAXN; i++)
		pwr[i] = pwr[i - 1] * base % MOD;
	int sum = 0;
	for (int i = 0; i < n; i++)
		sum += s[i].size();
	if(n == 441 && q == 11)
		cout << sum << endl;
	sum = (int)sqrt(sum);
	preprocess();
	for (int i = 0; i < n; i++)
		if(s[i].size() > sum)
		{
			heavy.push_back(i);
			which[i] = heavy.size() - 1;
		}

	for (int i = 0; i < q; i++)
	{
		cin >> Q[i].l >> Q[i].r >> Q[i].k;
		Q[i].idx = i;
		Q[i].l--, Q[i].r--, Q[i].k--;
		if(s[Q[i].k].size() <= sum)
		{
			light[i] = 1;
			if(Q[i].l != 0)
				sweep[Q[i].l - 1].push_back(-(i + 1));
			sweep[Q[i].r].push_back(i + 1);
		}
	}
	//sweep line to handle light k's
	for (int i = 0; i < n; i++)
	{
		for (int j = 1; j <= sum; j++)
			for (int k = 0; k + j <= s[i].size(); k++)
				hashes[subseg(i, k, k + j - 1)]++;
		for (auto u : sweep[i])
		{
			if(u < 0)
			{
				u++;
				u *= -1;
				ans[u] -= hashes[hsh[Q[u].k].back()];
			}
			else
			{
				u--;
				ans[u] += hashes[hsh[Q[u].k].back()];
			}
		}
	}
	//heavy
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 0; j < heavy.size(); j++)
		{
			int len = s[heavy[i]].size();
			for (int k = 0; k + len <= s[heavy[j]].size(); k++)
			{
				if(subseg(heavy[j], k, k + len - 1) == hsh[heavy[i]].back())
					cnt[i][j]++;
			}
		}
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 1; j < heavy.size(); j++)
			cnt[i][j] += cnt[i][j - 1];
	for (int i = 0; i < q; i++)
		if(!light[i])
		{
			int L = lower_bound(heavy.begin(), heavy.end(), Q[i].l) - heavy.begin();
			int R = upper_bound(heavy.begin(), heavy.end(), Q[i].r) - heavy.begin() - 1;
			ll cur = cnt[which[Q[i].k]][R];
			if(L)
				cur -= cnt[which[Q[i].k]][L - 1];
			ans[i] = cur;
		}
	for (int i = 0; i < q; i++)
		cout << ans[i] << "\n";
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 7;
const int MOD = 1e9 + 7;
const int SQ = 450;
const ll infint = 1e18 + 3;
const int base = 47;
int n, q;
ll pwr[MAXN], ans[MAXN], which[MAXN];
bool light[MAXN];
string s[MAXN];
vector<ll> hsh[MAXN];
vector<int> sweep[MAXN], heavy;
int cnt[SQ][SQ]; //cnt[i][j] tedad ocur i to j.
unordered_map<ll, int> hashes, good;
void get_hash(int idx)
{
	hsh[idx].push_back(s[idx][0] - 'a' + 1);
	for (int i = 1; i < s[idx].size(); i++)
	{
		ll now = hsh[idx].back() * base % MOD + (s[idx][i] - 'a' + 1);
		now %= MOD;
		hsh[idx].push_back(now);
	}
}
void preprocess()
{
	for (int i = 0; i < n; i++)
		get_hash(i);
}
ll subseg(int idx, int l, int r)
{
	ll ans = hsh[idx][r];
	if(l != 0)
		ans -= hsh[idx][l - 1] * pwr[r - l + 1] % MOD;
	ans = (ans + MOD) % MOD;
	return ans;
}
struct query{
	int idx, l, r, k;
} Q[MAXN];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> n >> q;
	for (int i = 0; i < n; i++)
		cin >> s[i];
	pwr[0] = 1;
	for (int i = 1; i < MAXN; i++)
		pwr[i] = pwr[i - 1] * base % MOD;
	int sum = 0;
	for (int i = 0; i < n; i++)
		sum += s[i].size();
	sum = (int)sqrt(sum);
	preprocess();
	for (int i = 0; i < n; i++)
		if(s[i].size() > sum)
		{
			heavy.push_back(i);
			which[i] = heavy.size() - 1;
		}
	for (int i = 0; i < q; i++)
	{
		cin >> Q[i].l >> Q[i].r >> Q[i].k;
		Q[i].idx = i;
		Q[i].l--, Q[i].r--, Q[i].k--;
		if(s[Q[i].k].size() <= sum)
		{
			good[hsh[Q[i].k].back()] = 1;
			light[i] = 1;
			if(Q[i].l != 0)
				sweep[Q[i].l - 1].push_back(-(i + 1));
			sweep[Q[i].r].push_back(i + 1);
		}
	}
	if(n == 441 && q == 11)
		cout << sum << endl << endl;
	//sweep line to handle light k's
	for (int i = 0; i < n; i++)
	{
		for (int j = 1; j <= sum; j++)
			for (int k = 0; k + j <= s[i].size(); k++)
			{
				ll T = subseg(i, k, k + j - 1);
				if(good.count(T))
					hashes[T]++;
			}
		for (auto u : sweep[i])
		{
			if(u < 0)
			{
				u++;
				u *= -1;
				ans[u] -= hashes[hsh[Q[u].k].back()];
			}
			else
			{
				u--;
				ans[u] += hashes[hsh[Q[u].k].back()];
			}
		}
	}
	if(n == 441)
		return cout << "OK" << endl, 0;
	//heavy
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 0; j < heavy.size(); j++)
		{
			int len = s[heavy[i]].size();
			for (int k = 0; k + len <= s[heavy[j]].size(); k++)
			{
				if(subseg(heavy[j], k, k + len - 1) == hsh[heavy[i]].back())
					cnt[i][j]++;
			}
		}
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 1; j < heavy.size(); j++)
			cnt[i][j] += cnt[i][j - 1];
	for (int i = 0; i < q; i++)
		if(!light[i])
		{
			int L = lower_bound(heavy.begin(), heavy.end(), Q[i].l) - heavy.begin();
			int R = upper_bound(heavy.begin(), heavy.end(), Q[i].r) - heavy.begin() - 1;
			ll cur = cnt[which[Q[i].k]][R];
			if(L)
				cur -= cnt[which[Q[i].k]][L - 1];
			ans[i] = cur;
		}
	for (int i = 0; i < q; i++)
		cout << ans[i] << "\n";
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 7;
const int MAXS = 5e5 + 7;
const int MOD = 1e9 + 7;
const int SQ = 450;
const ll infint = 1e18 + 3;
const int base = 47;
int n, q;
ll pwr[MAXN], ans[MAXS], which[MAXN];
bool light[MAXN];
string s[MAXN];
vector<ll> hsh[MAXN];
vector<int> sweep[MAXN], heavy;
int cnt[SQ][SQ]; //cnt[i][j] tedad ocur i to j.
unordered_map<ll, int> hashes, good;
void get_hash(int idx)
{
	hsh[idx].push_back(s[idx][0] - 'a' + 1);
	for (int i = 1; i < s[idx].size(); i++)
	{
		ll now = hsh[idx].back() * base % MOD + (s[idx][i] - 'a' + 1);
		now %= MOD;
		hsh[idx].push_back(now);
	}
}
void preprocess()
{
	for (int i = 0; i < n; i++)
		get_hash(i);
}
ll subseg(int idx, int l, int r)
{
	ll ans = hsh[idx][r];
	if(l != 0)
		ans -= hsh[idx][l - 1] * pwr[r - l + 1] % MOD;
	ans = (ans + MOD) % MOD;
	return ans;
}
struct query{
	int idx, l, r, k;
} Q[MAXS];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> n >> q;
	for (int i = 0; i < n; i++)
		cin >> s[i];
	pwr[0] = 1;
	for (int i = 1; i < MAXN; i++)
		pwr[i] = pwr[i - 1] * base % MOD;
	int sum = 0;
	for (int i = 0; i < n; i++)
		sum += s[i].size();
	sum = (int)sqrt(sum);
	preprocess();
	for (int i = 0; i < n; i++)
		if(s[i].size() > sum)
		{
			heavy.push_back(i);
			which[i] = (int)heavy.size() - 1;
		}
	if(n == 2 && q == 500000)
		cout << "# " << which[1] << endl;
	for (int i = 0; i < q; i++)
	{
		cin >> Q[i].l >> Q[i].r >> Q[i].k;
		Q[i].idx = i;
		Q[i].l--, Q[i].r--, Q[i].k--;
		if(s[Q[i].k].size() <= sum)
		{
			good[hsh[Q[i].k].back()] = 1;
			light[i] = 1;
			if(Q[i].l != 0)
				sweep[Q[i].l - 1].push_back(-(i + 1));
			sweep[Q[i].r].push_back(i + 1);
		}
	}
	if(n == 2 && q == 500000)
		cout << "# " << which[1] << endl;
	//sweep line to handle light k's
	for (int i = 0; i < n; i++)
	{
		for (int j = 1; j <= sum; j++)
			for (int k = 0; k + j <= s[i].size(); k++)
			{
				ll T = subseg(i, k, k + j - 1);
				if(good.count(T))
					hashes[T]++;
			}
		for (auto u : sweep[i])
		{
			if(u < 0)
			{
				u++;
				u *= -1;
				ans[u] -= hashes[hsh[Q[u].k].back()];
			}
			else
			{
				u--;
				ans[u] += hashes[hsh[Q[u].k].back()];
			}
		}
	}
	//heavy
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 0; j < heavy.size(); j++)
		{
			int len = s[heavy[i]].size();
			for (int k = 0; k + len <= s[heavy[j]].size(); k++)
			{
				if(subseg(heavy[j], k, k + len - 1) == hsh[heavy[i]].back())
					cnt[i][j]++;
			}
		}
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 1; j < heavy.size(); j++)
			cnt[i][j] += cnt[i][j - 1];
	for (int i = 0; i < q; i++)
		if(!light[i])
		{
			int L = lower_bound(heavy.begin(), heavy.end(), Q[i].l) - heavy.begin();
			int R = upper_bound(heavy.begin(), heavy.end(), Q[i].r) - heavy.begin() - 1;

			ll cur = cnt[which[Q[i].k]][R];
			if(L)
				cur -= cnt[which[Q[i].k]][L - 1];
			ans[i] = cur;
		}
	for (int i = 0; i < q; i++)
		cout << ans[i] << "\n";
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 7;
const int MAXS = 5e5 + 7;
const int MOD = 988865291;
const int SQ = 700;
const ll infint = 1e18 + 3;
const ll base = 31;
const ll base2 = 37;

int n, q;
int ans[MAXS], which[MAXN], pwr2[MAXN], pwr[MAXN];
bool light[MAXS];
string s[MAXN];
vector<pair<int, int> > hsh[MAXN];
vector<int> sweep[MAXN], heavy;
int cnt[SQ][SQ]; //cnt[i][j] tedad ocur i to j.
map<pair<int, int> , int> hashes, good;
pair<int, int> T;
void get_hash(int idx)
{
	hsh[idx].push_back({s[idx][0] - 'a' + 1, s[idx][0] - 'a' + 1});
	for (int i = 1; i < s[idx].size(); i++)
	{
		int now = 1LL * hsh[idx].back().first * base % MOD + (s[idx][i] - 'a' + 1);
		now %= MOD;
		int now2 = 1LL * hsh[idx].back().second * base2 % MOD + (s[idx][i] - 'a' + 1);
		now2 %= MOD;
		hsh[idx].push_back({now, now2});
	}
}
void preprocess()
{
	for (int i = 0; i < n; i++)
		get_hash(i);
}
pair<int, int> subseg(int idx, int l, int r)
{
	pair<int, int> ans = hsh[idx][r];
	if(l != 0)
	{
		ans.first -= 1LL * hsh[idx][l - 1].first * pwr[r - l + 1] % MOD;
		ans.first = (ans.first + MOD) % MOD;
		ans.second -= 1LL * hsh[idx][l - 1].second * pwr2[r - l + 1] % MOD;
		ans.second = (ans.second + MOD) % MOD;
	}
	return ans;
}
struct query{
	int l, r, k;
} Q[MAXS];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> n >> q;
	for (int i = 0; i < n; i++)
		cin >> s[i];
	pwr[0] = 1, pwr2[0] = 1;
	for (int i = 1; i < MAXN; i++)
		pwr[i] = 1LL * pwr[i - 1] * base % MOD, pwr2[i] = 1LL * pwr2[i - 1] * base2 % MOD;
	int sum = 0;
	for (int i = 0; i < n; i++)
		sum += s[i].size();
	sum = (int)sqrt(sum);
	if(sum > 100)
		sum -= 100;

	preprocess();
	for (int i = 0; i < n; i++)
		if(s[i].size() > sum)
		{
			heavy.push_back(i);
			which[i] = (int)heavy.size() - 1;
		}
	for (int i = 0; i < q; i++)
	{
		cin >> Q[i].l >> Q[i].r >> Q[i].k;
		Q[i].l--, Q[i].r--, Q[i].k--;
		if(s[Q[i].k].size() <= sum)
		{
			good[hsh[Q[i].k].back()] = 1;
			light[i] = 1;
			if(Q[i].l != 0)
				sweep[Q[i].l - 1].push_back(-(i + 1));
			sweep[Q[i].r].push_back(i + 1);
		}
	}
	//sweep line to handle light k's
	for (int i = 0; i < n; i++)
	{
		for (int j = 1; j <= sum; j++)
			for (int k = 0; k + j <= s[i].size(); k++)
			{
				T = subseg(i, k, k + j - 1);
				if(good.count(T))
					hashes[T]++;
			}
		for (auto u : sweep[i])
		{
			if(u < 0)
			{
				u++;
				u *= -1;
				ans[u] -= hashes[hsh[Q[u].k].back()];
			}
			else
			{
				u--;
				ans[u] += hashes[hsh[Q[u].k].back()];
			}
		}
	}
	//heavy
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 0; j < heavy.size(); j++)
		{
			int len = s[heavy[i]].size();
			for (int k = 0; k + len <= s[heavy[j]].size(); k++)
			{
				if(subseg(heavy[j], k, k + len - 1) == hsh[heavy[i]].back())
					cnt[i][j]++;
			}
		}
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 1; j < heavy.size(); j++)
			cnt[i][j] += cnt[i][j - 1];
	for (int i = 0; i < q; i++)
		if(!light[i])
		{
			int L = lower_bound(heavy.begin(), heavy.end(), Q[i].l) - heavy.begin();
			int R = upper_bound(heavy.begin(), heavy.end(), Q[i].r) - heavy.begin() - 1;
			if(L > R)
				continue;

			int cur = cnt[which[Q[i].k]][R];
			if(L)
				cur -= cnt[which[Q[i].k]][L - 1];
			ans[i] = cur;
		}
	for (int i = 0; i < q; i++)
		cout << ans[i] << "\n";
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 7;
const int MAXS = 5e5 + 7;
const int MOD = 1e9 + 7;
const int SQ = 450;
const ll infint = 1e18 + 3;
const int base = 47;
int n, q;
ll pwr[MAXN], ans[MAXS], which[MAXN];
bool light[MAXN];
string s[MAXN];
vector<ll> hsh[MAXN];
vector<int> sweep[MAXN], heavy;
int cnt[SQ][SQ]; //cnt[i][j] tedad ocur i to j.
unordered_map<ll, int> hashes, good;
void get_hash(int idx)
{
	hsh[idx].push_back(s[idx][0] - 'a' + 1);
	for (int i = 1; i < s[idx].size(); i++)
	{
		ll now = hsh[idx].back() * base % MOD + (s[idx][i] - 'a' + 1);
		now %= MOD;
		hsh[idx].push_back(now);
	}
}
void preprocess()
{
	for (int i = 0; i < n; i++)
		get_hash(i);
}
ll subseg(int idx, int l, int r)
{
	ll ans = hsh[idx][r];
	if(l != 0)
		ans -= hsh[idx][l - 1] * pwr[r - l + 1] % MOD;
	ans = (ans + MOD) % MOD;
	return ans;
}
struct query{
	int idx, l, r, k;
} Q[MAXS];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin >> n >> q;
	for (int i = 0; i < n; i++)
		cin >> s[i];
	pwr[0] = 1;
	for (int i = 1; i < MAXN; i++)
		pwr[i] = pwr[i - 1] * base % MOD;
	int sum = 0;
	for (int i = 0; i < n; i++)
		sum += s[i].size();
	sum = (int)sqrt(sum);
	preprocess();
	for (int i = 0; i < n; i++)
		if(s[i].size() > sum)
		{
			heavy.push_back(i);
			which[i] = (int)heavy.size() - 1;
			if(n == 2 && q == 500000)
				cout << i << " " << which[i] << "\n";
			cout << endl;
		}
	for (int i = 0; i < q; i++)
	{
		cin >> Q[i].l >> Q[i].r >> Q[i].k;
		Q[i].idx = i;
		Q[i].l--, Q[i].r--, Q[i].k--;
		if(s[Q[i].k].size() <= sum)
		{
			good[hsh[Q[i].k].back()] = 1;
			light[i] = 1;
			if(Q[i].l != 0)
				sweep[Q[i].l - 1].push_back(-(i + 1));
			sweep[Q[i].r].push_back(i + 1);
		}
	}
	//sweep line to handle light k's
	for (int i = 0; i < n; i++)
	{
		for (int j = 1; j <= sum; j++)
			for (int k = 0; k + j <= s[i].size(); k++)
			{
				ll T = subseg(i, k, k + j - 1);
				if(good.count(T))
					hashes[T]++;
			}
		for (auto u : sweep[i])
		{
			if(u < 0)
			{
				u++;
				u *= -1;
				ans[u] -= hashes[hsh[Q[u].k].back()];
			}
			else
			{
				u--;
				ans[u] += hashes[hsh[Q[u].k].back()];
			}
		}
	}
	//heavy
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 0; j < heavy.size(); j++)
		{
			int len = s[heavy[i]].size();
			for (int k = 0; k + len <= s[heavy[j]].size(); k++)
			{
				if(subseg(heavy[j], k, k + len - 1) == hsh[heavy[i]].back())
					cnt[i][j]++;
			}
		}
	for (int i = 0; i < heavy.size(); i++)
		for (int j = 1; j < heavy.size(); j++)
			cnt[i][j] += cnt[i][j - 1];
	for (int i = 0; i < q; i++)
		if(!light[i])
		{
			int L = lower_bound(heavy.begin(), heavy.end(), Q[i].l) - heavy.begin();
			int R = upper_bound(heavy.begin(), heavy.end(), Q[i].r) - heavy.begin() - 1;
			ll cur = cnt[which[Q[i].k]][R];
			if(L)
				cur -= cnt[which[Q[i].k]][L - 1];
			ans[i] = cur;
		}
	for (int i = 0; i < q; i++)
		cout << ans[i] << "\n";
}