#include <bits/stdc++.h>
using namespace std;

using ll = long long;

const int MAXN = 4.1e5;
int sa[MAXN];
int inv_sa[MAXN];
int longest[MAXN];
int classes[MAXN];
vector<int> indices[26];
int buf[MAXN];
int ptr[MAXN];

void gen_suffix_array(int n, const string& s) {
	for (int i = n-1; i >= 0; i--) {
		indices[s[i] - 'a'].push_back(i);
	}
	int cur = 0;
	for (int c = 0; c < 26; c++) {
		vector<int>& v = indices[c];
		for (int i = 0; i < (int)v.size(); i++) {
			sa[cur++] = v[i];
		}
	}
	for (int i = 0; i < n; i++) classes[i] = (int)s[i];
	for (int step = 1; step < n; step *= 2) {
		copy(classes, classes + n, buf);
		for (int i = 0; i < n; i++) {
			if (i > 0 && sa[i-1] + step < n 
				&& buf[sa[i-1]] == buf[sa[i]] 
				&& buf[sa[i-1] + step / 2] == buf[sa[i] + step / 2]) {
				classes[sa[i]] = classes[sa[i-1]];
			} else {
				classes[sa[i]] = i;
			}
		}
		for (int i = 0; i < n; i++) ptr[i] = i;
		copy(sa, sa + n, buf);
		for (int i = 0; i < n; i++) {
			int j = buf[i] - step;
			if (j >= 0) {
				sa[ptr[classes[j]]++] = j;
			}
		}
	}

	for (int i = 0; i < n; i++) inv_sa[sa[i]] = i;
	cur = 0;
	for (int z = 0; z < n; z++) {
		int i = inv_sa[z];
		if (cur) cur--;
		if (i+1 < n) {
			while (max(sa[i], sa[i+1]) + cur < n && s[sa[i] + cur] == s[sa[i+1] + cur]) {
				cur++;
			}
			longest[i] = cur;
		}
	}
}

const int L = 20;
int sparse[L+1][MAXN];

int main() {
	ios::sync_with_stdio(0), cin.tie(0);

	int n, qnum;
	cin >> n >> qnum;
	string s;
	cin >> s;
	gen_suffix_array(n, s);
	copy(longest, longest + (n-1), sparse[0]);
	for (int l = 0; l < L; l++) {
		int step = 1 << l;
		if (2 * step >= n) break;
		for (int i = 0; i + 2 * step < n; i++) {
			sparse[l + 1][i] = min(sparse[l][i], sparse[l][i + step]);
		}
	}
	auto longest_query = [&](int a, int b) -> int {
		if (a == b) return n - a;
		a = inv_sa[a];
		b = inv_sa[b];
		if (a > b) swap(a, b);
		int l = 31 - __builtin_clz(b - a);
		return min(sparse[l][a], sparse[l][b - (1 << l)]);
	};
	for (int _ = 0; _ < qnum; _++) {
		int snum, mod;
		cin >> snum >> mod;
		vector<pair<int, int>> substrings(snum);
		for (auto& z : substrings) {
			cin >> z.first >> z.second;
			z.first--;
			z.second -= z.first;
		}
		sort(substrings.begin(), substrings.end(), [&](const pair<int, int>& a, const pair<int, int>& b) {
			int val = longest_query(a.first, b.first);
			if (val >= min(a.second, b.second)) {
				// one is a prefix of the other
				return a.second < b.second;
			} else {
				return s[a.first + val] < s[b.first + val];
			}
		});
		vector<pair<int, int>> combine(snum - 1);
		for (int i = 0; i+1 < snum; i++) {
			auto& a = substrings[i];
			auto& b = substrings[i+1];
			int zz = min({longest_query(a.first, b.first), a.second, b.second});
			combine[i] = {zz, i};
		}
		sort(combine.begin(), combine.end());
		reverse(combine.begin(), combine.end());
		vector<int> par(snum, -1);
		vector<int> ans(snum, 2 % mod);
		function<int(int)> getpar = [&](int a) {
			return par[a] < 0 ? a : (par[a] = getpar(par[a]));
		};
		for (auto z : combine) {
			int a = getpar(z.second);
			int b = getpar(z.second + 1);
			ll num_ways;
			if (-par[a] == 1 && substrings[a].second == z.first) {
				num_ways = (1 + ans[b]) % mod;
			} else {
				num_ways = ll(ans[a]) * ans[b] % mod;
			}
			if (-par[a] < -par[b]) swap(a, b);
			par[a] += par[b];
			par[b] = a;
			ans[a] = num_ways;
		}
		cout << ans[getpar(0)] << '\n';
	}

	return 0;
}
