#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;
}