#include <bits/stdc++.h>
template <typename ty>
void read(ty &x) {
  x = 0;
  int f = 1;
  char ch = getchar();
  while (ch > '9' || ch < '0') {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') {
    x = x * 10 + ch - '0';
    ch = getchar();
  }
  x *= f;
}
template <typename ty>
ty Max(ty a, ty b) {
  return a > b ? a : b;
}
template <typename ty>
ty Min(ty a, ty b) {
  return a < b ? a : b;
}
template <typename ty>
ty Chkmax(ty &a, ty b) {
  return a < b ? a = b, 1 : 0;
}
template <typename ty>
ty Chkmin(ty &a, ty b) {
  return a > b ? a = b, 1 : 0;
}
using namespace std;
const int inf = 1e9;
const int N = 5e5 + 16;
const int M = 1e5 + 16;
const int P = 1e7;
pair<int, int> ans[N];
int rt[M];
int m, q;
char s[N], t[N];
vector<int> vec[M];
struct query {
  int id, l, r, ql, qr;
  bool operator<(const query &ot) const { return qr < ot.qr; }
} Q[N];
void get(int i) {
  read(Q[i].l);
  read(Q[i].r);
  read(Q[i].ql);
  read(Q[i].qr);
  Q[i].id = i;
}
struct segment_tree {
  int cnt, mx[P], c[P][2], pos[P];
  void init() { cnt = 0; }
  void pushup(int rt) {
    pos[rt] = pos[mx[c[rt][1]] > mx[c[rt][0]] ? c[rt][1] : c[rt][0]];
    mx[rt] = Max(mx[c[rt][1]], mx[c[rt][0]]);
  }
  void insert(int &rt, int l, int r, int x) {
    if (!rt) rt = ++cnt;
    if (l == r) {
      pos[rt] = x;
      mx[rt]++;
      return;
    }
    int mid = l + r >> 1;
    if (x <= mid)
      insert(c[rt][0], l, mid, x);
    else
      insert(c[rt][1], mid + 1, r, x);
    pushup(rt);
  }
  int merge(int x, int y, int l, int r) {
    if (!x || !y) return x + y;
    if (l == r) {
      mx[x] += mx[y];
      return x;
    }
    int mid = l + r >> 1;
    c[x][0] = merge(c[x][0], c[y][0], l, mid);
    c[x][1] = merge(c[x][1], c[y][1], mid + 1, r);
    pushup(x);
    return x;
  }
  pair<int, int> query(int rt, int l, int r, int x, int y) {
    if (!rt || r < x || y < l) return make_pair(0, -x);
    if (x <= l && r <= y) return make_pair(mx[rt], -pos[rt]);
    int mid = l + r >> 1;
    return Max(query(c[rt][0], l, mid, x, y),
               query(c[rt][1], mid + 1, r, x, y));
  }
} SEG;
struct suffix_automation {
  int ch[M][27], fa[M][21], len[M], last, sz, to[M], nxt[M], hd[M], s;
  void init() { last = sz = 1; }
  void insert(int c, int val) {
    int np = ++sz, p = last;
    last = np;
    len[np] = len[p] + 1;
    SEG.insert(rt[sz], 1, m, val);
    for (; p && !ch[p][c]; p = fa[p][0]) ch[p][c] = np;
    if (!p) {
      fa[np][0] = 1;
      return;
    }
    int q = ch[p][c];
    if (len[q] == len[p] + 1)
      fa[np][0] = q;
    else {
      int nq = ++sz;
      memcpy(ch[nq], ch[q], sizeof ch[q]);
      len[nq] = len[p] + 1;
      fa[nq][0] = fa[q][0];
      fa[q][0] = fa[np][0] = nq;
      for (; ch[p][c] == q; p = fa[p][0]) ch[p][c] = nq;
    }
  }
  void end() {
    for (int i = (1), iend = (20); i <= iend; ++i)
      for (int j = (1), jend = (sz); j <= jend; ++j)
        fa[j][i] = fa[fa[j][i - 1]][i - 1];
  }
  void build() {
    for (int i = (2), iend = (sz); i <= iend; ++i) {
      to[++s] = i;
      nxt[s] = hd[fa[i][0]];
      hd[fa[i][0]] = s;
    }
  }
  void dfs(int x) {
    for (int i = hd[x]; i; i = nxt[i])
      dfs(to[i]), rt[x] = SEG.merge(rt[x], rt[to[i]], 1, m);
    int sz = vec[x].size();
    for (int i = (0), iend = (sz); i < iend; ++i)
      ans[Q[vec[x][i]].id] =
          SEG.query(rt[x], 1, m, Q[vec[x][i]].l, Q[vec[x][i]].r);
  }
  void calc() { dfs(1); }
} SAM;
int main() {
  SAM.init();
  SEG.init();
  scanf("%s", s + 1);
  int len = strlen(s + 1);
  read(m);
  for (int i = (1), iend = (m); i <= iend; ++i) {
    scanf("%s", t + 1);
    SAM.last = 1;
    int l = strlen(t + 1);
    for (int j = (1), jend = (l); j <= jend; ++j) SAM.insert(t[j] - 'a', i);
  }
  SAM.end();
  read(q);
  for (int i = (1), iend = (q); i <= iend; ++i) get(i);
  sort(Q + 1, Q + q + 1);
  int nowlen = 0, now = 1, head = 1;
  for (int i = 1; i <= len; ++i) {
    while (now && !SAM.ch[now][s[i] - 'a'])
      now = SAM.fa[now][0], nowlen = SAM.len[now];
    if (SAM.ch[now][s[i] - 'a'])
      now = SAM.ch[now][s[i] - 'a'], nowlen++;
    else
      now = 1, nowlen = 0;
    int tmpnow = now;
    while (head <= q && Q[head].qr == i) {
      tmpnow = now;
      int length = Q[head].qr - Q[head].ql + 1, id = Q[head].id;
      if (nowlen < length) {
        ans[id] = make_pair(0, -Q[head].l);
      } else {
        for (int i = (20), ibgn = (0); i >= ibgn; --i)
          if (length <= SAM.len[SAM.fa[tmpnow][i]]) tmpnow = SAM.fa[tmpnow][i];
        vec[tmpnow].push_back(head);
      }
      head++;
    }
  }
  SAM.build();
  SAM.calc();
  for (int i = (1), iend = (q); i <= iend; ++i)
    printf("%d %d\n", -ans[i].second, ans[i].first);
  return 0;
}
