#include <bits/stdc++.h>
using namespace std;
inline int read() {
  int X = 0;
  char ch = 0, minus = 0;
  while (ch < 48 || ch > 57) ch = getchar(), minus |= ch == '-';
  while (ch >= 48 && ch <= 57) X = X * 10 + (ch ^ 48), ch = getchar();
  return minus ? -X : X;
}
struct Node {
  int t[26], len, f;
} a[50500 << 1];
int tn, las;
void add(int c) {
  int p = las, np = ++tn;
  las = np;
  a[np].len = a[p].len + 1;
  for (; p && !a[p].t[c]; p = a[p].f) a[p].t[c] = np;
  if (!p)
    a[np].f = 1;
  else {
    int v = a[p].t[c];
    if (a[v].len == a[p].len + 1)
      a[np].f = v;
    else {
      int nv = ++tn;
      a[nv] = a[v];
      a[nv].len = a[p].len + 1;
      for (; p && a[p].t[c] == v; p = a[p].f) a[p].t[c] = nv;
      a[np].f = a[v].f = nv;
    }
  }
}
struct SGT_Node {
  int l, r, x, p;
} b[50500 * 41];
int tot, rt[50500 << 1];
void up(int num) {
  int l = b[num].l, r = b[num].r;
  if (b[r].x > b[l].x) {
    b[num].x = b[r].x;
    b[num].p = b[r].p;
  } else {
    b[num].x = b[l].x;
    b[num].p = b[l].p;
  }
}
int to;
void change(int l, int r, int &num) {
  if (!num) num = ++tot;
  if (l == r) {
    b[num].x++;
    b[num].p = l;
    return;
  }
  int mid = (l + r) >> 1;
  if (to <= mid)
    change(l, mid, b[num].l);
  else
    change(mid + 1, r, b[num].r);
  up(num);
}
int wfl, wfr, ansx, ansp;
void query(int l, int r, int num) {
  if (wfl <= l && r <= wfr) {
    if (b[num].x > ansx) {
      ansx = b[num].x;
      ansp = b[num].p;
    }
    return;
  }
  int mid = (l + r) >> 1;
  if (wfl <= mid) query(l, mid, b[num].l);
  if (mid < wfr) query(mid + 1, r, b[num].r);
}
int merge(int x, int y) {
  if (!x || !y) return x | y;
  int pos = ++tot;
  if (!(b[x].l | b[x].r)) {
    b[pos].x = b[x].x + b[y].x;
    b[pos].p = b[x].p;
  } else {
    b[pos].l = merge(b[x].l, b[y].l);
    b[pos].r = merge(b[x].r, b[y].r);
    up(pos);
  }
  return pos;
}
vector<int> g[50500 << 1];
void dfs(int num) {
  for (int i = 0, v; i < g[num].size(); i++) {
    dfs(v = g[num][i]);
    rt[num] = merge(rt[num], rt[v]);
  }
}
int f[50500 << 1][16];
int find(int pos, int len) {
  int k = 15;
  while (k--)
    while (a[f[pos][k]].len >= len) pos = f[pos][k];
  return pos;
}
char s[500500], _str[50500], *ss = _str, *str[50500];
int sl[50500], pos[500500], slen[500500], len, n, q;
int main() {
  scanf("%s", s + 1);
  len = strlen(s + 1);
  n = read();
  tn = 1;
  for (int i = 1; i <= n; i++) {
    las = 1;
    scanf("%s", str[i] = ss);
    sl[i] = strlen(str[i]);
    for (int j = 0; j < sl[i]; j++) add(str[i][j] -= 'a');
    ss += sl[i];
  }
  for (int i = 2; i <= tn; i++) g[f[i][0] = a[i].f].push_back(i);
  for (int i = 1; i <= n; i++) {
    int p = 1;
    for (int j = 0; j < sl[i]; j++) {
      p = a[p].t[str[i][j]];
      to = i;
      change(1, n, rt[p]);
    }
  }
  dfs(1);
  for (int j = 1; j < 15; j++)
    for (int i = 1; i <= n; i++) f[i][j] = f[f[i][j - 1]][j - 1];
  for (int i = 1, p = 1, plen = 0; i <= len; i++) {
    s[i] -= 'a';
    while (p > 1 && !a[p].t[s[i]]) {
      p = a[p].f;
      plen = a[p].len;
    }
    if (a[p].t[s[i]]) {
      p = a[p].t[s[i]];
      plen++;
    }
    pos[i] = p;
    slen[i] = plen;
  }
  q = read();
  for (int i = 1, pl, pr; i <= q; i++) {
    wfl = read();
    wfr = read();
    pl = read();
    pr = read();
    pl = pr - pl + 1;
    if (slen[pr] < pl) {
      printf("%d 0\n", wfl);
      continue;
    }
    pl = find(pos[pr], pl);
    ansp = ansx = 0;
    query(1, n, rt[pl]);
    if (!ansx) ansp = wfl;
    printf("%d %d\n", ansp, ansx);
  }
  return 0;
}
