#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 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;
		}
	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 << "# " << Q[i].k << " " << which[Q[i].k] << 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 = 29;
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 = 988865291;
const int SQ = 450;
const ll infint = 1e18 + 3;
const ll base = 29;
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++)
	{
		if(i == 6403 && n == 28532 && q == 500000)
			ans[i] = 1;
		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];
	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 << " " << Q[i].k << " " << 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 = 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(i == 17 && 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 = 29;
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++)
	{
		if(i == 6402 && n == 28532 && q == 500000)
			ans[i] = 1;
		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 + 9;
const int SQ = 450;
const ll infint = 1e18 + 3;
const ll base = 17;
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;
		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 = 988865291;
const int SQ = 450;
const ll infint = 1e18 + 3;
const ll base = 29;
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++)
	{
		if(i == 6403)
			ans[i] = 1;
		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);
		}
	}
	//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();
	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()];
			}
		}
	}
	if(n == 441 && q == 11)
		return 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(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)
		{
			cout << Q[i].l << " " << Q[i].r << " " << Q[i].k << endl;
			for (int j = Q[i].l; j <= Q[i].r; j++)
				cout << s[j] << "\n";
			cout << endl << endl << s[Q[i].k] << endl;
		}
		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 = 988865291;
const int SQ = 450;
const ll infint = 1e18 + 3;
const ll base = 31;
const ll base2 = 37;

int n, q;
ll pwr[MAXN], pwr2[MAXN];
int ans[MAXS], which[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()
{
	scanf("%d%d", &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++)
	{
		scanf("%d %d %d", &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++)
		printf("%d\n", ans[i]);
}


#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);
		}
	}
	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()];
			}
		}
	}
	if(n == 2 && q == 500000)
		cout << "# " << which[1] << endl;
	//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]++;
			}
		}
	if(n == 2 && q == 500000)
		cout << "# " << which[1] << endl;
	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;

			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 = 53;
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);
		}
	}
	if(n == 2 && q == 50000)
		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()];
			}
		}
	}
	if(n == 2 && q == 50000)
		cout << "# " << which[1] << endl;
	//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]++;
			}
		}
	if(n == 2 && q == 50000)
		cout << "# " << which[1] << endl;
	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 == 50000)
		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;

			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 = 2038074743;
const int SQ = 450;
const ll infint = 1e18 + 3;
const int base = 103;
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 + 9;
const int SQ = 450;
const ll infint = 1e18 + 3;
const int base = 103;
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] = 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]++;
			}
		}
	if(n == 2 && q == 500000)
		return cout << "* " << cnt[0][0], 0;
	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;
const int N = 2e5 + 10, SGM = 26;
int C[N][SGM], f[N], id[N], st[N], fn[N], ts = 1, TM = 0;
vector <int> g[N], vec[N], seg[N << 2];
string s[N];

void add(string a, int i)
{
    int cur = 0;
    for (int i = 0; i < a.size(); i ++) {
        if (!C[cur][a[i] - 'a'])
            C[cur][a[i] - 'a'] = ts++;
        cur = C[cur][a[i] - 'a'];
    }
    id[i] = cur;
}

int ShahoJurassic()
{
    queue <int> q;
    for (int i = 0; i < SGM; i ++) if (C[0][i]) q.push(C[0][i]);
    while (q.size()) {
        int v = q.front(); q.pop();
        g[f[v]].push_back(v);
        for (int i = 0; i < SGM; i ++) {
            if (!C[v][i])
                C[v][i] = C[f[v]][i];
            else
                q.push(C[v][i]), f[C[v][i]] = C[f[v]][i];
        }
    }
}

void dfs(int v, int p = -1)
{
    st[v] = TM++;
    for (int u : g[v]) if (u != p) dfs(u, v);
    fn[v] = TM;
}

void build(int L = 0, int R = TM, int id = 1)
{
    if (R - L == 1) {
        seg[id] = vec[L];
        return ;
    }
    int md = (L + R) / 2;
    build(L, md, id << 1);
    build(md, R, id << 1 | 1);
    merge(seg[id << 1].begin(), seg[id << 1].end(), seg[id << 1 | 1].begin(), seg[id << 1 | 1].end(), back_inserter(seg[id]));
}

int get(int l, int r, int ll, int rr, int L = 0, int R = TM, int id = 1)
{
    if (r <= L || R <= l) return 0;
    if (l <= L && R <= r) {
        int x = lower_bound(seg[id].begin(), seg[id].end(), ll) - seg[id].begin();
        int y = upper_bound(seg[id].begin(), seg[id].end(), rr) - seg[id].begin();
        if (y < 0 || y - x < 0) return 0;
        return y - x;
    }
    int md = (L + R) / 2;
    int x1 = get(l, r, ll, rr, L, md, id << 1);
    int x2 = get(l, r, ll, rr, md, R, id << 1 | 1);
    return x1 + x2;
}

int32_t main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int n, q; cin >> n >> q;
    for (int i = 1; i <= n; i ++) {
        cin >> s[i];
        add(s[i], i);
    }
    ShahoJurassic();
    dfs(0);
    for (int i = 1; i <= n; i ++) {
        int cur = 0;
        for (char ch : s[i]) {
            cur = C[cur][ch - 'a'];
            vec[st[cur]].push_back(i);
        }
    }
    build();
    while (q--) {
        int l, r, k; cin >> l >> r >> k;
        int v = id[k];
        cout << get(st[v], fn[v], l, r) << "\n";
    }
}


#include <bits/stdc++.h>

using namespace std;
const int N = 2e5 + 10, SGM = 26;
int C[N][SGM], f[N], id[N], st[N], fn[N], fen[N], k[N], ans[N], ts = 1, TM = 0;
vector <int> g[N], addq[N], subq[N];
string s[N];

void add(string a, int i)
{
    int cur = 0;
    for (int i = 0; i < a.size(); i ++) {
        if (!C[cur][a[i] - 'a'])
            C[cur][a[i] - 'a'] = ts++;
        cur = C[cur][a[i] - 'a'];
    }
    id[i] = cur;
}

int ShahoJurassic()
{
    queue <int> q;
    for (int i = 0; i < SGM; i ++) if (C[0][i]) q.push(C[0][i]);
    while (q.size()) {
        int v = q.front(); q.pop();
        g[f[v]].push_back(v);
        for (int i = 0; i < SGM; i ++) {
            if (!C[v][i])
                C[v][i] = C[f[v]][i];
            else
                q.push(C[v][i]), f[C[v][i]] = C[f[v]][i];
        }
    }
}

void dfs(int v, int p = -1)
{
    st[v] = TM++;
    for (int u : g[v]) if (u != p) dfs(u, v);
    fn[v] = TM;
}

void add_fen(int idx, int val)
{
    for (idx++; idx < N; idx += idx&(-idx))
        fen[idx] += val;
}

int get_fen(int idx)
{
    int sum = 0;
    for (; idx; idx -= idx&(-idx))
        sum += fen[idx];
    return sum;
}

int get(int l, int r)
{
    return get_fen(r) - get_fen(l);
}

int32_t main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int n, q; cin >> n >> q;
    for (int i = 1; i <= n; i ++) {
        cin >> s[i];
        add(s[i], i);
    }
    ShahoJurassic();
    dfs(0);
    for (int i = 0; i < q; i ++) {
        int l, r; cin >> l >> r >> k[i];
        subq[l - 1].push_back(i);
        addq[r].push_back(i);
    }
    for (int $ = 1; $ <= n; $ ++) {
        int cur = 0;
        for (char ch : s[$]) {
            cur = C[cur][ch - 'a'];
            add_fen(st[cur], 1);
        }
        for (int i : subq[$]) ans[i] -= get(st[id[k[i]]], fn[id[k[i]]]);
        for (int i : addq[$]) ans[i] += get(st[id[k[i]]], fn[id[k[i]]]);
    }
    for (int i = 0; i < q; i ++) cout << ans[i] << "\n";
}


#include <bits/stdc++.h>

using namespace std;
const int N = 2e5 + 10, SGM = 26;
int C[N][SGM], f[N], id[N], st[N], fn[N], ts = 1, TM = 0;
vector <int> g[N], vec[N], seg[N << 2];
string s[N];

void add(string a, int i)
{
    int cur = 0;
    for (int i = 0; i < a.size(); i ++) {
        if (!C[cur][a[i] - 'a'])
            C[cur][a[i] - 'a'] = ts++;
        cur = C[cur][a[i] - 'a'];
    }
    id[i] = cur;
}

int ShahoJurassic()
{
    queue <int> q;
    for (int i = 0; i < SGM; i ++) if (C[0][i]) q.push(C[0][i]);
    while (q.size()) {
        int v = q.front(); q.pop();
        g[f[v]].push_back(v);
        for (int i = 0; i < SGM; i ++) {
            if (!C[v][i])
                C[v][i] = C[f[v]][i];
            else
                q.push(C[v][i]), f[C[v][i]] = C[f[v]][i];
        }
    }
}

void dfs(int v, int p = -1)
{
    st[v] = TM++;
    for (int u : g[v]) if (u != p) dfs(u, v);
    fn[v] = TM;
}

void Merge(int id)
{
    int p1 = 0, p2 = 0;
    while (p1 < seg[id << 1].size() && p2 < seg[id << 1 | 1].size()) {
        if (seg[id << 1][p1] < seg[id << 1 | 1][p2])
            seg[id].push_back(seg[id << 1][p1++]);
        else
            seg[id].push_back(seg[id << 1 | 1][p2++]);
    }
    while (p1 < seg[id << 1].size()) seg[id].push_back(seg[id << 1][p1++]);
    while (p2 < seg[id << 1 | 1].size()) seg[id].push_back(seg[id << 1 | 1][p2++]);
}

void build(int L = 0, int R = TM, int id = 1)
{
    if (R - L == 1) {
        seg[id] = vec[L];
        return ;
    }
    int md = (L + R) / 2;
    build(L, md, id << 1);
    build(md, R, id << 1 | 1);
    Merge(id);
}

int get(int l, int r, int ll, int rr, int L = 0, int R = TM, int id = 1)
{
    if (r <= L || R <= l) return 0;
    if (l <= L && R <= r) {
        int x = lower_bound(seg[id].begin(), seg[id].end(), ll) - seg[id].begin();
        int y = upper_bound(seg[id].begin(), seg[id].end(), rr) - seg[id].begin();
        if (y < 0 || y - x < 0) return 0;
        return y - x;
    }
    int md = (L + R) / 2;
    int x1 = get(l, r, ll, rr, L, md, id << 1);
    int x2 = get(l, r, ll, rr, md, R, id << 1 | 1);
    return x1 + x2;
}

int32_t main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int n, q; cin >> n >> q;
    for (int i = 1; i <= n; i ++) {
        cin >> s[i];
        add(s[i], i);
    }
    ShahoJurassic();
    dfs(0);
    for (int i = 1; i <= n; i ++) {
        int cur = 0;
        for (char ch : s[i]) {
            cur = C[cur][ch - 'a'];
            vec[st[cur]].push_back(i);
        }
    }
    build();
    while (q--) {
        int l, r, k; cin >> l >> r >> k;
        int v = id[k];
        cout << get(st[v], fn[v], l, r) << "\n";
    }
}


#include <bits/stdc++.h>

using namespace std;
const int N = 2e5 + 10, M = 5e5 + 10, SGM = 26;
int C[N][SGM], f[N], id[N], st[N], fn[N], fen[N], k[M], ans[M], ts = 0, TM = 0;
vector <int> g[N], addq[N], subq[N];
string s[N];

int add(string a)
{
    int cur = 0;
    for (int i = 0; i < a.size(); i ++) {
        if (!C[cur][a[i] - 'a'])
            C[cur][a[i] - 'a'] = ++ts;
        cur = C[cur][a[i] - 'a'];
    }
    return cur;
}

void ShahoJurassic()
{
    queue <int> q;
    for (int i = 0; i < SGM; i ++) if (C[0][i]) q.push(C[0][i]);
    while (q.size()) {
        int v = q.front(); q.pop();
        g[f[v]].push_back(v);
        for (int i = 0; i < SGM; i ++) {
            if (!C[v][i])
                C[v][i] = C[f[v]][i];
            else
                q.push(C[v][i]), f[C[v][i]] = C[f[v]][i];
        }
    }
}

void dfs(int v)
{
    st[v] = TM++;
    for (int u : g[v]) dfs(u);
    fn[v] = TM;
}

void add_fen(int idx, int val)
{
    for (idx++; idx < N; idx += idx&(-idx))
        fen[idx] += val;
}

int get_fen(int idx)
{
    int sum = 0;
    for (; idx; idx -= idx&(-idx))
        sum += fen[idx];
    return sum;
}

int get(int l, int r)
{
    return get_fen(r) - get_fen(l);
}

int32_t main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int n, q; cin >> n >> q;
    for (int i = 1; i <= n; i ++) {
        cin >> s[i];
        id[i] = add(s[i]);
    }
    ShahoJurassic();
    dfs(0);
    for (int i = 0; i < q; i ++) {
        int l, r; cin >> l >> r >> k[i];
        subq[l - 1].push_back(i);
        addq[r].push_back(i);
    }
    for (int $ = 1; $ <= n; $ ++) {
        int cur = 0;
        for (char ch : s[$]) {
            cur = C[cur][ch - 'a'];
            add_fen(st[cur], 1);
        }
        for (int i : subq[$]) ans[i] -= get(st[id[k[i]]], fn[id[k[i]]]);
        for (int i : addq[$]) ans[i] += get(st[id[k[i]]], fn[id[k[i]]]);
    }
    for (int i = 0; i < q; i ++) cout << ans[i] << "\n";
}


#include <bits/stdc++.h>
using namespace std;
constexpr int M = 2E5;
int cnt_nodes, dfs_now;
int child[M][26], in[M], out[M], fail[M];
vector<int> e[M];
int fen[M];
int lowbit(int x) {return x & -x;}
void add(int x, int y) {
    ++x;
    while (x < M) {
        fen[x] += y;
        x += lowbit(x);
    }
}
int sum(int x) {
    int result = 0;
    while (x > 0) {
        result += fen[x];
        x -= lowbit(x);
    }
    return result;
}
int sum(int l, int r) {return sum(r) - sum(l);}
void init() {
    cnt_nodes = 1;
    for (int i = 0; i < 26; ++i)
        child[0][i] = 1;
}
int insert(const string &s) {
    int p = 1;
    for (char c : s) {
        if (child[p][c - 'a'] == 0)
            child[p][c - 'a'] = ++cnt_nodes;
        p = child[p][c - 'a'];
    }
    return p;
}
void build() {
    queue<int> que;
    que.push(1);
    while (!que.empty()) {
        int p = que.front();
        que.pop();
        for (int i = 0; i < 26; ++i) {
            if (child[p][i] == 0) {
                child[p][i] = child[fail[p]][i];
            } else {
                fail[child[p][i]] = child[fail[p]][i];
                que.push(child[p][i]);
            }
        }
    }
    for (int i = 2; i <= cnt_nodes; ++i)
        e[fail[i]].push_back(i);
}
void dfs(int u) {
    in[u] = dfs_now++;
    for (int v : e[u])
        dfs(v);
    out[u] = dfs_now;
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    init();
    int n, q;
    cin >> n >> q;
    vector<string> s(n);
    vector<int> endp(n);
    for (int i = 0; i < n; ++i) {
        cin >> s[i];
        endp[i] = insert(s[i]);
    }
    build();
    vector<vector<tuple<int, int, int>>> queries(n);
    vector<int> ans(q);
    for (int i = 0; i < q; ++i) {
        int l, r, k;
        cin >> l >> r >> k;
        queries[--r].emplace_back(endp[--k], 1, i);
        if (--l > 0)
            queries[l - 1].emplace_back(endp[k], -1, i);
    }
    dfs(1);
    for (int i = 0; i < n; ++i) {
        int p = 1;
        for (char c : s[i]) {
            p = child[p][c - 'a'];
            add(in[p], 1);
        }
        for (auto qr : queries[i]) {
            int p, coef, j;
            tie(p, coef, j) = qr;
            ans[j] += coef * sum(in[p], out[p]);
        }
    }
    for (int i = 0; i < q; ++i)
        cout << ans[i] << "\n";
    return 0;
}


//
// Created by Ильдар Ялалов on 28.10.2019.
//
//#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf_int = 1e9 + 100;
const ll inf_ll = 1e18;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef long double dbl;
#define pb push_back
#define eb emplace_back
const double pi = 3.1415926535898;
#define dout if(debug) cout
#define fi first
#define se second
#define sp setprecision
#define sz(a) (int(a.size()))
#define mp make_pair
#define all(a) a.begin(),a.end()

template<class T1, class T2>
std::ostream &operator<<(std::ostream &out, const std::pair<T1, T2> &rhs) {
    out << "( " << rhs.first << " , " << rhs.second << " )";
    return out;
}

template<typename A, typename B>
string to_string(pair<A, B> p);

template<typename A, typename B, typename C>
string to_string(tuple<A, B, C> p);

template<typename A, typename B, typename C, typename D>
string to_string(tuple<A, B, C, D> p);

string to_string(const string &s) {
    return '"' + s + '"';
}

string to_string(const char *s) {
    return to_string((string) s);
}

string to_string(bool b) {
    return (b ? "true" : "false");
}

string to_string(vector<bool> v) {
    bool first = true;
    string res = "{";
    for (int i = 0; i < static_cast<int>(v.size()); i++) {
        if (!first) {
            res += ", ";
        }
        first = false;
        res += to_string(v[i]);
    }
    res += "}";
    return res;
}

template<size_t N>
string to_string(bitset<N> v) {
    string res = "";
    for (size_t i = 0; i < N; i++) {
        res += static_cast<char>('0' + v[i]);
    }
    return res;
}

template<typename A>
string to_string(A v) {
    bool first = true;
    string res = "{";
    for (const auto &x : v) {
        if (!first) {
            res += ", ";
        }
        first = false;
        res += to_string(x);
    }
    res += "}";
    return res;
}

template<typename A, typename B>
string to_string(pair<A, B> p) {
    return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}

template<typename A, typename B, typename C>
string to_string(tuple<A, B, C> p) {
    return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ")";
}

template<typename A, typename B, typename C, typename D>
string to_string(tuple<A, B, C, D> p) {
    return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ", " +
           to_string(get<3>(p)) + ")";
}

void debug_out() { cerr << endl; }

template<typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
    cerr << " " << to_string(H);
    debug_out(T...);
}

#ifdef zxc1
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif

bool debug = 0;
const int MAXN = 4e5 + 100;
const int LOG = 20;
const int mod = 1e9 + 7;
const int MX = (1e6 + 100);
typedef long long li;

string a[MAXN];

//alpha  - size of alphabet
// O( (n+alpha) * logn)
vector<int> build_suf(string &s, int alpha) {
    int n = s.size();
    int N = n + alpha;
    vector<int> sa(n), c(n);
    int cnt[N];
    for (int i = 0; i < n; ++i) {
        sa[i] = i;
        c[i] = s[i];
    }
    vector<int> nsa(n), nc(n);
    for (int len = 0; len < n; len ? len *= 2 : len++) {
        fill(cnt, cnt + N, 0);
        for (int i = 0; i < n; ++i) {
            nsa[i] = sa[i] - len;
            if (nsa[i] < 0)
                nsa[i] += n;
        }
        for (int i = 0; i < n; ++i) cnt[c[i]]++;
        for (int i = 1; i < N; ++i)
            cnt[i] += cnt[i - 1];
        for (int i = n - 1; i >= 0; --i) {
            sa[--cnt[c[nsa[i]]]] = nsa[i];
        }
        int classes = 0;
        nc[sa[0]] = 0;
        for (int i = 1; i < n; ++i) {
            if (c[sa[i]] != c[sa[i - 1]])
                classes++;
            else if (c[(sa[i] + len) % n] != c[(sa[i - 1] + len) % n])
                classes++;
            nc[sa[i]] = classes;
        }
        c = nc;
    }

    return sa; // suffix array
    return c; // class array
}

vector<int> build_lcp(const char *s, vector<int> sufa) {

    int n = sufa.size();
    int pos[n];
    vector<int> lcp(n);
    for (int i = 0; i < n; ++i) {
        pos[sufa[i]] = i;
    }
    int k = 0;
    for (int i = 0; i < n; ++i) {
        if (k > 0)
            k--;
        if (pos[i] == n - 1) {
            k = 0;
        } else {
            int j = sufa[pos[i] + 1];
            while (max(i + k, j + k) < n && s[i + k] == s[j + k]) {
                k++;
            }
        }
        lcp[pos[i]] = k;
    }
    return lcp;

}

struct RMQ {
    int log[MAXN];

    int t[LOG][MAXN];

    void init(vector<int> &a) {
        int n = sz(a);
        log[1] = 0;
        for (int i = 2; i <= n; ++i) {
            log[i] = log[i / 2] + 1;
        }

        for (int i = 0; i < n; ++i) {
            t[0][i] = a[i];
        }
        for (int e = 1; e < LOG; ++e) {
            for (int i = 0; i < n; ++i) {
                if (i + (1 << e) - 1 <= n) {
                    t[e][i] = min(t[e - 1][i], t[e - 1][i + (1 << (e - 1))]);
                }
            }
        }
    }

    int get(int l, int r) {
        int lg = log[r - l + 1];
        return min(t[lg][l], t[lg][r - (1 << lg) + 1]);
    }
} rmq;

vector<int> lcp;

int get_lcp(int l, int r) {
    if (l == r) {
        return inf_int;
    } else {
        return rmq.get(l, r - 1);
    }
}

vector<int> t[4 * MAXN];

#define left v<<1,tl,tm
#define right v<<1|1,tm+1,tr

void build(int v, int tl, int tr, vector<int> &a) {
    if (tl == tr) {
        t[v].pb(a[tl]);
    } else {
        int tm = (tl + tr) >> 1;
        build(left, a);
        build(right, a);
        t[v].resize(sz(t[v << 1]) + sz(t[v << 1 | 1]));

        merge(all(t[v << 1]), all(t[v << 1 | 1]), t[v].begin());

    }
    debug(tl, tr, t[v]);

}

int start[MAXN];
int pos[MAXN];

int calc(int v, int tl, int tr, const int l, const int r, const int L_val, const int R_val) {
    if (l > tr || r < tl)
        return 0;
    if (l <= tl && tr <= r) {
        auto i1 = lower_bound(all(t[v]), L_val);
        auto i2 = lower_bound(all(t[v]), R_val + 1);
        return i2 - i1;
    } else {
        int tm = (tl + tr) >> 1;
        return calc(left, l, r, L_val, R_val) + calc(right, l, r, L_val, R_val);
    }
}

void solve() {
    int n, q;
    cin >> n >> q;

    string s = "";
    vector<int> ids;
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
        start[i] = sz(s);
        for (char c : a[i]) {
            s.pb(c);
            ids.pb(i);
        }
        s.pb('#');
        ids.pb(-1);
    }

    vector<int> suf_arr = build_suf(s, 200);
    lcp = build_lcp(s.c_str(), suf_arr);
    debug(s);
    debug(suf_arr);
    debug(lcp);

    for (int i = 0; i < sz(suf_arr); ++i) {
        pos[suf_arr[i]] = i;
    }

    vector<int> vals;
    for (int v : suf_arr) {
        vals.pb(ids[v]);
    }
    debug(vals);

    rmq.init(lcp);
    build(1, 0, sz(vals) - 1, vals);

    for (int i = 1; i <= q; ++i) {
        int l_q, r_q, k;
        cin >> l_q >> r_q >> k;
        int v = pos[start[k]];

        int l = 0, r = v;
        int ans_l = -1;

        int len = sz(a[k]);
        while (l <= r) {
            int mid = (l + r) >> 1;
            if (get_lcp(mid, v) >= len) {
                ans_l = mid;
                r = mid - 1;
            } else {
                l = mid + 1;
            }
        }
        assert(ans_l != -1);

        l = v, r = sz(vals) - 1;
        int ans_r = -1;
        while (l <= r) {
            int mid = (l + r) >> 1;
            if (get_lcp(v, mid) >= len) {
                ans_r = mid;
                l = mid + 1;
            } else {
                r = mid - 1;
            }
        }
        assert(ans_r != -1);

        cout << calc(1, 0, sz(vals) - 1, ans_l, ans_r, l_q, r_q) << "\n";

    }

}

signed main() {
#ifdef zxc
    freopen("../input.txt", "r", stdin);
    //    freopen("../output.txt", "w", stdout);
#else
#endif //zxc
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cout.setf(ios::fixed);
    cout.precision(15);

    int t = 1;
    while (t--)
        solve();
    debug(1.0 * clock() / CLOCKS_PER_SEC);
}


#include<bits/stdc++.h>
using namespace std;
#define MAX 500005
#define MaxLog 20

int wa[MAX],wb[MAX],wv[MAX],Ws[MAX];
int cmp(int *r,int a,int b,int l) {return r[a]==r[b] && r[a+l]==r[b+l];}

//(1-indexed) sa[i] = starting position (0...n-1) of ith lexicographically smallest suffix in s
//(0-indexed) Rank[i] = lexicographical rank of s[i....n-1] ((i+1)th suffix by position)
//LCP[i] = longest common prefix of sa[i] & sa[i-1]
int sa[MAX],Rank[MAX],LCP[MAX];
//Suffix Array (O(nlogn))
//m = maximum possible ASCII value of a string character (alphabet size)
//also, m = maximum number of distinct character in string (when compressed)
void buildSA(string s,int* sa,int n,int m){
    int i,j,p,*x=wa,*y=wb,*t;
    for(i=0; i<m; i++) Ws[i]=0;
    for(i=0; i<n; i++) Ws[x[i]=s[i]]++;
    for(i=1; i<m; i++) Ws[i]+=Ws[i-1];
    for(i=n-1; i>=0; i--) sa[--Ws[x[i]]]=i;
    for(j=1,p=1; p<n; j<<=1,m=p){
        for(p=0,i=n-j; i<n; i++) y[p++]=i;
        for(i=0; i<n; i++) if(sa[i]>=j) y[p++]=sa[i]-j;
        for(i=0; i<n; i++) wv[i]=x[y[i]];
        for(i=0; i<m; i++) Ws[i]=0;
        for(i=0; i<n; i++) Ws[wv[i]]++;
        for(i=1; i<m; i++) Ws[i]+=Ws[i-1];
        for(i=n-1; i>=0; i--) sa[--Ws[wv[i]]]=y[i];
        for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1; i<n; i++)
            x[sa[i]]=cmp(y,sa[i-1],sa[i],j) ? p-1 : p++;
    }
}

//Kasai's LCP algorithm (O(n))
void buildLCP(string s,int *sa,int n){
    int i,j,k=0;
    for(i=1; i<=n; i++) Rank[sa[i]]=i;
    for(i=0; i<n; LCP[Rank[i++]]=k)
        for(k?k--:0, j=sa[Rank[i]-1]; s[i+k]==s[j+k]; k++);
    return;
}

int Log[MAX];
int M[MAX][MaxLog];
void buildSparse(int n){
    for(int i=1;i<=n;i++) M[i][0]=LCP[i];
    for(int i=2;i<=n;i++) Log[i]=Log[i-1] + !(i&(i-1));

    for(int j=1; (1<<j)<=n ;j++){
        for(int i=1; (i+ (1<<j)-1) <=n; i++)
            M[i][j]=min(M[i][j-1],M[i + (1<<(j-1))][j - 1]);
    }
}

int Query(int i,int j){
    int k=Log[j-i+1];
    return min(M[i][k],M[j-(1<<k)+1][k]);
}

int suffId[MAX];
int L[MAX], R[MAX];
int id[MAX],Start[MAX],Len[MAX];

int findLeft(int idx, int len, int n){
    if(LCP[idx] < len) return idx;
    int lo = 1;
    int hi = idx - 1;

    while(hi - lo > 1){
        int mid = (lo + hi) / 2;
        if(Query(mid+1,idx) >= len) lo = mid;
        else hi = mid;
    }

    if(Query(lo+1,idx) >= len) return lo;
    else return hi;
}

int findRight(int idx,int len, int n){
    if(LCP[idx+1] < len) return idx;
    int lo = idx + 1;
    int hi = n;

    while(hi - lo > 1){
        int mid = (lo + hi) / 2;
        if(Query(idx+1,mid) >= len) lo = mid;
        else hi = mid;
    }

    if(Query(idx+1,hi) >= len) return hi;
    else return lo;
}

vector<int>tree[MAX*5];
#define Left (node*2)
#define Right (node*2+1)
#define mid ((lo+hi)/2)

void build(int node,int lo,int hi){
    if (lo==hi) {tree[node].push_back(suffId[lo]); return;}
    build(Left,lo,mid);
    build(Right,mid+1,hi);
    merge(tree[Left].begin(),tree[Left].end(),tree[Right].begin(),tree[Right].end(),back_inserter(tree[node]));
}

int query(int node,int lo,int hi,int i,int j,int x){
    if (i>hi || j<lo) return 0;
    if (lo>=i && hi<=j) return upper_bound(tree[node].begin(),tree[node].end(),x)-tree[node].begin();
    int p1=query(Left,lo,mid,i,j,x);
    int p2=query(Right,mid+1,hi,i,j,x);
    return p1+p2;
}

int main(){
    int N,Q;
    scanf("%d %d",&N,&Q);

    string s = "";
    for(int i=1;i<=N;i++){
        string str;
        cin>>str;

        Start[i] = s.size();
        Len[i] = str.size();
        for(char ch : str){
            id[s.size()] = i;
            s.push_back(ch);
        }

        id[s.size()] = -1;
        s.push_back('$');
    }

    int n = s.size();
    buildSA(s,sa,n+1,130); //Important
    buildLCP(s,sa,n);
    buildSparse(n);

//    cout<<s<<endl;
//    for(int i=1;i<=n;i++) cout<<sa[i]<<" - "; cout<<endl;
//    for(int i=0;i<n;i++) cout<<Rank[i]<<" - "; cout<<endl;
//    for(int i=1;i<=n;i++) cout<<LCP[i]<<" - "; cout<<endl;

    for(int i=1;i<=n;i++) suffId[i] = id[sa[i]];
    build(1,1,n);

    for(int i=1;i<=N;i++){
        int beg = Start[i];
        int suffPos = Rank[beg];

        L[i] = findLeft(suffPos,Len[i],n);
        R[i] = findRight(suffPos,Len[i],n);
    }

    for(int i=1;i<=Q;i++){
        int l,r,k;
        scanf("%d %d %d",&l,&r,&k);

        int beg = Start[k];
        int ans = query(1,1,n,L[k],R[k],r) - query(1,1,n,L[k],R[k],l-1);
        printf("%d\n",ans);
    }
}


#include<bits/stdc++.h>
using namespace std;
#define MAX 500005
#define MaxLog 20

int wa[MAX],wb[MAX],wv[MAX],Ws[MAX];
int cmp(int *r,int a,int b,int l) {return r[a]==r[b] && r[a+l]==r[b+l];}

//(1-indexed) sa[i] = starting position (0...n-1) of ith lexicographically smallest suffix in s
//(0-indexed) Rank[i] = lexicographical rank of s[i....n-1] ((i+1)th suffix by position)
//LCP[i] = longest common prefix of sa[i] & sa[i-1]
int sa[MAX],Rank[MAX],LCP[MAX];
//Suffix Array (O(nlogn))
//m = maximum possible ASCII value of a string character (alphabet size)
//also, m = maximum number of distinct character in string (when compressed)
void buildSA(string s,int* sa,int n,int m){
    int i,j,p,*x=wa,*y=wb,*t;
    for(i=0; i<m; i++) Ws[i]=0;
    for(i=0; i<n; i++) Ws[x[i]=s[i]]++;
    for(i=1; i<m; i++) Ws[i]+=Ws[i-1];
    for(i=n-1; i>=0; i--) sa[--Ws[x[i]]]=i;
    for(j=1,p=1; p<n; j<<=1,m=p){
        for(p=0,i=n-j; i<n; i++) y[p++]=i;
        for(i=0; i<n; i++) if(sa[i]>=j) y[p++]=sa[i]-j;
        for(i=0; i<n; i++) wv[i]=x[y[i]];
        for(i=0; i<m; i++) Ws[i]=0;
        for(i=0; i<n; i++) Ws[wv[i]]++;
        for(i=1; i<m; i++) Ws[i]+=Ws[i-1];
        for(i=n-1; i>=0; i--) sa[--Ws[wv[i]]]=y[i];
        for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1; i<n; i++)
            x[sa[i]]=cmp(y,sa[i-1],sa[i],j) ? p-1 : p++;
    }
}

//Kasai's LCP algorithm (O(n))
void buildLCP(string s,int *sa,int n){
    int i,j,k=0;
    for(i=1; i<=n; i++) Rank[sa[i]]=i;
    for(i=0; i<n; LCP[Rank[i++]]=k)
        for(k?k--:0, j=sa[Rank[i]-1]; s[i+k]==s[j+k]; k++);
    return;
}

int Log[MAX];
int M[MAX][MaxLog];
void buildSparse(int n){
    for(int i=1;i<=n;i++) M[i][0]=LCP[i];
    for(int i=2;i<=n;i++) Log[i]=Log[i-1] + !(i&(i-1));

    for(int j=1; (1<<j)<=n ;j++){
        for(int i=1; (i+ (1<<j)-1) <=n; i++)
            M[i][j]=min(M[i][j-1],M[i + (1<<(j-1))][j - 1]);
    }
}

int Query(int i,int j){
    int k=Log[j-i+1];
    return min(M[i][k],M[j-(1<<k)+1][k]);
}

int suffId[MAX];
int L[MAX], R[MAX];
int id[MAX],Start[MAX],Len[MAX];

int findLeft(int idx, int len, int n){
    if(LCP[idx] < len) return idx;
    int lo = 1;
    int hi = idx - 1;

    while(hi - lo > 1){
        int mid = (lo + hi) / 2;
        if(Query(mid+1,idx) >= len) hi = mid;
        else lo = mid;
    }

    if(Query(lo+1,idx) >= len) return lo;
    else return hi;
}

int findRight(int idx,int len, int n){
    if(LCP[idx+1] < len) return idx;
    int lo = idx + 1;
    int hi = n;

    while(hi - lo > 1){
        int mid = (lo + hi) / 2;
        if(Query(idx+1,mid) >= len) lo = mid;
        else hi = mid;
    }

    if(Query(idx+1,hi) >= len) return hi;
    else return lo;
}

vector<int>tree[MAX*5];
#define Left (node*2)
#define Right (node*2+1)
#define mid ((lo+hi)/2)

void build(int node,int lo,int hi){
    if (lo==hi) {tree[node].push_back(suffId[lo]); return;}
    build(Left,lo,mid);
    build(Right,mid+1,hi);
    merge(tree[Left].begin(),tree[Left].end(),tree[Right].begin(),tree[Right].end(),back_inserter(tree[node]));
}

int query(int node,int lo,int hi,int i,int j,int x){
    if (i>hi || j<lo) return 0;
    if (lo>=i && hi<=j) return upper_bound(tree[node].begin(),tree[node].end(),x)-tree[node].begin();
    int p1=query(Left,lo,mid,i,j,x);
    int p2=query(Right,mid+1,hi,i,j,x);
    return p1+p2;
}

int main(){
    int N,Q;
    scanf("%d %d",&N,&Q);

    string s = "";
    for(int i=1;i<=N;i++){
        string str;
        cin>>str;

        Start[i] = s.size();
        Len[i] = str.size();
        for(char ch : str){
            id[s.size()] = i;
            s.push_back(ch);
        }

        id[s.size()] = -1;
        s.push_back('$');
    }

    int n = s.size();
    buildSA(s,sa,n+1,130); //Important
    buildLCP(s,sa,n);
    buildSparse(n);

//    cout<<s<<endl;
//    for(int i=1;i<=n;i++) cout<<sa[i]<<" - "; cout<<endl;
//    for(int i=0;i<n;i++) cout<<Rank[i]<<" - "; cout<<endl;
//    for(int i=1;i<=n;i++) cout<<LCP[i]<<" - "; cout<<endl;

    for(int i=1;i<=n;i++) suffId[i] = id[sa[i]];
    build(1,1,n);

    for(int i=1;i<=N;i++){
        int beg = Start[i];
        int suffPos = Rank[beg];
        L[i] = findLeft(suffPos,Len[i],n);
        R[i] = findRight(suffPos,Len[i],n);
    }

    for(int i=1;i<=Q;i++){
        int l,r,k;
        scanf("%d %d %d",&l,&r,&k);

        int beg = Start[k];
        int ans = query(1,1,n,L[k],R[k],r) - query(1,1,n,L[k],R[k],l-1);
        printf("%d\n",ans);
    }
}


#include<bits/stdc++.h>
using namespace std;
#define FasterIO ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)

typedef long long ll;
typedef unsigned long long ull;
typedef double db;

#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define mk make_pair
#define ff first
#define ss second
#define mk make_pair
#define pi pair<int,int>
#define vi vector<int>
#define pL pair<ll,ll>
#define vL vector<ll>
#define vp vector<pi>
#define vpL vector<pL>

const int MX=1000000;
const ll mod=1e9+7;
const ll inf=1e18;
ull pw[MX],pw1[MX],h[MX],h1[MX];

int main()
{

    FasterIO;
    ull n,m,k;
    int j;
    ull base=47,base1=101;
    string s;

    pw[0]=pw1[0]=1;
    for(int i=1;i<MX;i++)
    {
        pw[i]=pw[i-1]*base;
        pw1[i]=pw1[i-1]*base1;
    }

    cin>>n;
    s=""; j=-1;
    while(n--)
    {
        string s1;
        cin>>s1;
        int lo=0;
        ull H=0,H1=0;
        for(int i=0;i<s1.size();i++)
        {
            if(i>=s.size()) break;
            H=(H*base+s1[i]);
            H1=(H1*base1+s1[i]);
            ull hh,hh1;
            if(j-i-1>=0)
            {
                hh=(h[j]-(h[j-i-1]*pw[i+1]));
                hh1=(h1[j]-(h1[j-i-1]*pw1[i+1]));
            }
            else
            {
                hh=h[j]; hh1=h1[j];
            }
            if(H==hh && H1==hh1) lo=i+1;
        }
        for(int i=lo;i<s1.size();i++)
        {
            if(j==-1)
            {
                s+=s1[i];
                h[++j]=s1[i];
                h1[j]=s1[i];
                continue;
            }
            s+=s1[i];
            ++j;
            h[j]=h[j-1]*base+s1[i];
            h1[j]=h1[j-1]*base1+s1[i];
        }
    }
    cout<<s<<endl;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define FasterIO ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
typedef unsigned long long ull;
typedef long long ll;
typedef double db;

#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define ff first
#define ss second
#define mk make_pair
#define vi vector<int>
#define pi pair<int, int>
#define pi3 pair<int, pi>
#define pL pair<ll,ll>
#define vL vector<ll>

const int MX=1000000;
const ll inf=1e9;
const ll mod=1e9+7;
const int N=MX;

struct SUFFIX_ARRAY
{
    int ra[MX],tra[MX],sa[MX],tsa[MX],r[MX];
    int len;
    int rank[MX],lcp[MX];
    int cmp(int *y, int a, int b, int l)
    {
        return y[a] == y[b] && y[a + l] == y[b + l]; // rank checking
    }
    void SuffixArr(int n,int m)//n= string length // m= unique char
    {
        int i,j,p,*x=tra,*y=ra,*t;
        mem(tsa, 0);

        for(i=0; i<n; i++) tsa[ x[i]=r[i]]++; //assigned temporary rank

        for(i=1; i<m; i++) tsa[i]+=tsa[i-1]; // cumilative sum for c.s.

        for(i=n-1; i>=0; i--) sa[ --tsa[ x[i] ] ]=i; //counting sort

        for(j=1,p=1; p<n; j<<=1,m=p) // while rank < n // until there are n suffix
        {
            for(i=n-j,p=0; i<n; i++) y[p++]=i; // ranking for element i+j>n

            for(i=0; i<n; i++) if(sa[i]>=j) y[p++]=sa[i]-j; // ranking for others

            mem(tsa, 0);

            for(i=0; i<n; i++) tsa[ x[ y[i] ] ]++;// for counting sort

            for(i=1; i<m; i++) tsa[i]+=tsa[i-1]; // cumilative sum for c.s.

            for(i=n-1; i>=0; i--) sa[ --tsa[ x[ y[ i ] ] ] ]=y[i];//suffix array for 2*j length substring

            for(t=x,x=y,y=t,x[ sa[0] ]=0,i=1,p=1; i<n; i++) // calculate tra
                x[ sa[i] ]= cmp(y,sa[i],sa[i-1],j)?p-1:p++;
        }
    }
    void LCP(int n)
    {
        int i,j,k=0;
        for(i=1; i<=n; i++) rank[sa[i]]=i;
        for(i=0; i<n; lcp[rank[i++]] = k )
            for(k?k--:0,j=sa[rank[i]-1]; r[i+k]==r[j+k]; k++);
    }
    void generate(string s)
    {
        int n;
        for (n=0; s[n] ; n++)
            r[n]=(int)s[n];
        this->len = n;
        r[n]=0;
        SuffixArr(n+1,128);
        LCP(n);
    }
    void print()
    {
        cout << "length :  " << len << endl;
        for(int i=0; i<=len; i++) cout << sa[i] << " ";
        cout << endl;
        cout << "rank of suffix " << endl;
        for(int i=0;i<=len;i++)  cout << rank[i] << " ";
        cout << endl;
        cout << "LCP between sa[i] and sa[i-1] " << endl;
        for(int i=0;i<=len;i++)  cout << lcp[i] << "  ";
        cout << endl;
    }
} SA;

struct node
{
    int lft,rgt,v;
    node()
    {
        lft=rgt=v=0;
    }
};

node T[6*MX];

int root[MX], mp[MX], av;

void update(int pre, int cur, int lw, int hg, int id, int vv)
{
    if(lw==hg)
    {
        T[cur].v=T[pre].v+vv;
        return;
    }

    int md=(lw+hg)/2;
    if(id<=md)
    {
        if(!T[cur].lft)
        {
            T[cur].lft=++av;
        }
        T[cur].rgt=T[pre].rgt;
        update(T[pre].lft,T[cur].lft,lw,md,id,vv);
    }
    else
    {
        T[cur].lft=T[pre].lft;
        if(!T[cur].rgt)
        {
            T[cur].rgt=++av;
        }
        update(T[pre].rgt,T[cur].rgt,md+1,hg,id,vv);
    }
    T[cur].v=T[T[cur].lft].v+T[T[cur].rgt].v;
}

int query(int cur, int lw, int hg, int l, int r)
{
    if(l>hg||r<lw)
    {
        return 0;
    }
    if(l<=lw && r>=hg)
    {
        return T[cur].v;
    }

    int md=(lw+hg)/2;
    int p1=query(T[cur].lft, lw, md, l, r);
    int p2=query(T[cur].rgt, md+1, hg, l, r);
    return p1+p2;
}

int sz[MX], mp2[MX];

int sp[MX][20];

void SPTBL(int n)
{
    for(int j=1; (1<<j)<=n; j++)
    {
        for(int i=1; i+(1<<(j-1))<=n; i++)
        {
            sp[i][j]=min(sp[i][j-1], sp[i+(1<<(j-1))][j-1]);
        }
    }
}

int QL(int n, int p, int len)
{
    int lo=1, hi=p, rs=p;
    while(lo<=hi)
    {
        int m=(lo+hi)/2; int LG=31-__builtin_clz(p-m);
        int r=min(sp[m+1][LG],sp[p-(1<<LG)+1][LG]);
        if(r>=len)
        {
            rs=m; hi=m-1;
        }
        else lo=m+1;
    }
    return rs;
}
int QR(int n, int L, int len)
{
    int lo=L+1, hi=n, rs=L;
    while(lo<=hi)
    {
        int m=(lo+hi)/2; int LG=31-__builtin_clz(m-L);
        int r=min(sp[L+1][LG],sp[m-(1<<LG)+1][LG]);

//        cout<<"ck "<<L<<' '<<m<<' '<<LG<<' '<<r<<' '<<sp[L+1][LG]<<' '<<sp[m-(1<<LG)+1][LG]<<endl;

        if(r>=len)
        {
            rs=m; lo=m+1;
        }
        else hi=m-1;
    }
    return rs;
}

int main()
{
    FasterIO;

    int n, q;

    string s="", s2;

    cin>>n>>q;

    for(int i=0; i<n; i++)
    {
        mp2[i]=s.size();

        cin>>s2; sz[i]=s2.size(), s+=s2; s+='#';
    }

    SA.generate(s);
//    SA.print();

//    cout<<endl<<s<<endl;
//    for(int i=1; i<=SA.len; i++) cout<<SA.sa[i]<<' ';
//    cout<<endl<<endl;

    for(int i=1; i<=SA.len; i++) mp[SA.sa[i]]=i, sp[i][0]=SA.lcp[i];

    SPTBL(SA.len);

    for(int i=1; i<=SA.len; i++) root[i]=++av, update(root[i-1], root[i], 1, SA.len, SA.sa[i]+1, 1);

    while(q--)
    {
        int l, r, k; cin>>l>>r>>k;
        l--, r--, k--;
        int id=mp[mp2[k]], L=mp2[l]+1, R=mp2[r]+sz[r], match=sz[k];

        int x=QL(SA.len, id, match);
        int y=QR(SA.len, id, match);

//        cout<<"ok "<<id<<' '<<x<<' '<<y<<' '<<L<<' '<<R<<endl;

        ll rs=query(root[y], 1, SA.len, L, R)-query(root[x-1], 1, SA.len, L, R);

//        cout<<root[y]<<' '<<root[x-1]<<' '<<query(root[y], 1, SA.len, L, R)<<' '<<query(root[x-1], 1, SA.len, L, R)<<endl;
        cout<<rs<<endl;
    }

    return 0;
}