rt,用的是 ymx 大佬的莫队 + SA 做法
// author: lzyqwq
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#include <ext/pb_ds/tree_policy.hpp>
// #include<ext/pb_ds/priority_queue.hpp>
#define PQ priority_queue
#define co const
#define TOSNU tree_order_statistics_node_update
#define RB rb_tree_tag
#define NP null_type
#define eb emplace_back
#define ep emplace
#define bg begin
// #define int long long
// #define int __int128
#define gp gp_hash_table
#define cc cc_hash_table
#define umap unordered_map
#define uset unordered_set
#define mset multiset
#define mmap multimap
#define lbd lower_bound
#define ubd upper_bound
#define P pair
#define fi first
#define se second
#define mk make_pair
#define vec vector
#define mst memset
#define sof sizeof
#define sort stable_sort
#define reset(x, y) mst(x, y, sof(x))
#define lb(x) ((x) & -(x))
// #define ls(x) ((x) << 1)
// #define rs(x) ((x) << 1 | 1)
#define Max(u, v, w) u = max(v, w)
#define Min(u, v, w) u = min(v, w)
#define cmax(u, v) u = max(u, v)
#define cmin(u, v) v = min(u, v)
using i64 = long long; using u64 = unsigned i64; using db = double;
using i128 = __int128; using namespace std; using str = string;
// using namespace __gnu_pbds;
// using namespace __gnu_cxx;
mt19937 rnd(time(0));
// mt19937_64 rnd(time(0));
co int N = 6e5, M = 1919810, B1 = 780, B2 = 300, S = 50001; co db eps = 1e-9;
int range(int l, int r) { return rnd() % (r - l + 1) + l; }
// i64 range(i64 l, i64 r) { return rnd() % (r - l + 1) + l; }
// co int mod = 1e9 + 7;
// co i64 mod = 1e9 + 7;
// co i128 mod = 1e9 + 7;
co int inf = 0x3f3f3f3f; co i64 Inf = 0x3f3f3f3f3f3f3f3f;
template<class T> void read(T &x) {
x = 0; T f = 1; char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = -1;
for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - 48; x *= f;
}
template<class T> void write(co T x) {
if (x > 9) write(x / 10); putchar(x % 10 + 48);
}
template<class T> void print(T x, co char ed = '\n') {
if (x < 0) putchar('-'), x = -x; write(x), putchar(ed);
}
str s; int n, m, q, a[N], ord = 26, col[N], hd[S], len[S];
void init_main() {
// freopen("pid.in", "r", stdin);
// freopen("pid.out", "w", stdout);
}
void qingkong() {
}
struct SuffixArray {
int rk[N], sa[N], st[20][N], cnt[N], ht[N], lg[N]; P<P<int, int>, int> p[N];
void init() {
for (int i = 1; i <= n; ++i) ++cnt[a[i]];
for (int i = 1; i <= ord; ++i) cnt[i] += cnt[i - 1];
for (int i = 1; i <= n; ++i) rk[i] = cnt[a[i] - 1] + 1;
}
void Sort() {
for (int l = 1, id; l <= n; l <<= 1) {
for (int i = 1; i <= n; ++i)
p[i] = {{rk[i], i + l > n ? 0 : rk[i + l]}, i};
sort(p + 1, p + n + 1); id = 0;
for (int i = 1; i <= n; ++i) {
if (i == 1 || p[i].fi != p[i - 1].fi) ++id; rk[p[i].se] = id;
}
if (id == n) break;
}
for (int i = 1; i <= n; ++i) sa[rk[i]] = i;
}
void height() {
for (int i = 1, j, k = 0; i <= n; ++i) {
if (rk[i] == 1) { ht[1] = k = 0; continue; }
if (k) --k; j = sa[rk[i] - 1];
while (i + k <= n && j + k <= n && a[i + k] == a[j + k]) ++k;
ht[rk[i]] = k;
}
}
void ST() {
for (int i = 1; i <= n; ++i) st[0][i] = ht[i], lg[i] = __lg(i);
for (int i = 1; i <= lg[n]; ++i)
for (int j = 1; j + (1 << i) - 1 <= n; ++j)
Min(st[i][j], st[i - 1][j], st[i - 1][j + (1 << (i - 1))]);
}
int LCP(int l, int r) {
if (l == r) return n - sa[l] + 1; if (l > r) swap(l, r); ++l;
int k = lg[r - l + 1]; return min(st[k][l], st[k][r - (1 << k) + 1]);
}
void work() { init(); Sort(); height(); ST(); }
void debug() {
for (int i = 1; i <= n; ++i) cout << rk[i] << ' '; cout << '\n';
for (int i = 1; i <= n; ++i) cout << sa[i] << ' '; cout << '\n';
}
} SA;
struct Query { int l, r, ql, qr, v, id; } Q[N];
struct Node { int id, cnt; } ans[N];
bool operator<(Node u, Node v) {
return u.cnt != v.cnt ? u.cnt > v.cnt : u.id < v.id;
}
int cnt[S], bel[S], tot, num[200][S], bl[200], br[200], mx[200];
void add(int x) {
--num[bel[x]][cnt[x]]; ++cnt[x];
++num[bel[x]][cnt[x]]; cmax(mx[bel[x]], cnt[x]);
}
void del(int x) {
if (cnt[x] == mx[bel[x]] && num[bel[x]][cnt[x]] == 1) --mx[bel[x]];
--num[bel[x]][cnt[x]]; --cnt[x]; ++num[bel[x]][cnt[x]];
}
Node query(int l, int r) {
if (bel[l] == bel[r]) {
Node ret = {1919810, 0};
for (int i = l; i <= r; ++i) ret = min(ret, {i, cnt[i]}); return ret;
}
int occ = 0;
for (int i = bel[l] + 1; i < bel[r]; ++i) cmax(occ, mx[i]);
for (int i = l; i <= br[bel[l]]; ++i) cmax(occ, cnt[i]);
for (int i = bl[bel[r]]; i <= r; ++i) cmax(occ, cnt[i]);
for (int i = l; i <= br[bel[l]]; ++i) if (cnt[i] == occ) return {i, cnt[i]};
for (int i = bel[l] + 1; i < bel[r]; ++i)
if (mx[i] == occ)
for (int j = bl[i]; j <= br[i]; ++j)
if (cnt[j] == occ) return {j, cnt[j]};
for (int i = bl[bel[r]]; i <= r; ++i) if (cnt[i] == occ) return {i, cnt[i]};
return {114514, 1919810};
}
void work(co int testcase) {
qingkong(); cin >> s >> m;
for (int i = 0, l = s.size(); i < l; ++i) a[++n] = s[i] - 'a' + 1;
for (int i = 1; i <= m; ++i) {
cin >> s; ++ord; a[++n] = ord; len[i] = s.size(); hd[i] = n + 1;
for (int j = 0; j < len[i]; ++j) a[++n] = s[j] - 'a' + 1;
if (i % B2 == 1) ++tot; bel[i] = tot;
}
for (int i = 1; i <= tot; ++i) bl[i] = br[i - 1] + 1, Min(br[i], i * B2, m);
SA.work(); cin >> q;
// SA.debug();
for (int i = 1; i <= m; ++i)
for (int j = hd[i]; j < hd[i] + len[i]; ++j) col[SA.rk[j]] = i;
for (int i = 1, l, r, ll, rr; i <= q; ++i) {
cin >> Q[i].ql >> Q[i].qr >> ll >> rr; l = 1, r = SA.rk[ll];
Q[i].l = Q[i].r = 0;
while (l <= r) {
int mid = (l + r) >> 1;
if (SA.LCP(mid, SA.rk[ll]) >= rr - ll + 1) Q[i].l = mid, r = mid - 1;
else l = mid + 1;
}
l = SA.rk[ll]; r = n;
while (l <= r) {
int mid = (l + r) >> 1;
if (SA.LCP(mid, SA.rk[ll]) >= rr - ll + 1) Q[i].r = mid, l = mid + 1;
else r = mid - 1;
}
Q[i].v = Q[i].l / B1; Q[i].id = i;
}
sort(Q + 1, Q + 1 + q, [&](Query x, Query y) {
return x.v != y.v ? x.v < y.v : (x.v & 1) ? x.r < y.r : x.r > y.r;
});
for (int i = 1; i <= tot; ++i) num[i][0] = br[i] - bl[i] + 1;
for (int i = 1, l = 1, r = 0; i <= q; ++i) {
while (l > Q[i].l) add(col[--l]); while (r < Q[i].r) add(col[++r]);
while (l < Q[i].l) del(col[l++]); while (r > Q[i].r) del(col[r--]);
ans[Q[i].id] = query(Q[i].ql, Q[i].qr);
}
for (int i = 1; i <= q; ++i) cout << ans[i].id << ' ' << ans[i].cnt << '\n';
}
signed main() {
cin.tie(0), cout.tie(0), ios::sync_with_stdio(0);
init_main(); int testcases = 1;
// cin >> testcases;
// read(testcases);
for (int lzyqwq = 1; lzyqwq <= testcases; ++lzyqwq) work(lzyqwq); return 0;
}