#include <bits/stdc++.h>
using namespace std;
const int N = 500100, MM = 50010;
const int TOT = MM << 1;
struct node {
  int num, mx, l, r;
} T[MM * 17];
int rt[TOT], bz[TOT][17], trans[TOT][26];
int num, pos, ll, rr, ans1, ans2;
int m, root = 1, la = 1, tot = 1, fa[TOT], maxlen[TOT];
inline void pp(int ind) {
  if (T[T[ind].l].num >= T[T[ind].r].num) {
    T[ind].mx = T[T[ind].l].mx;
    T[ind].num = T[T[ind].l].num;
  } else {
    T[ind].mx = T[T[ind].r].mx;
    T[ind].num = T[T[ind].r].num;
  }
}
void add(int &ind, int l, int r) {
  if (!ind) T[ind = ++num].mx = l;
  if (l == r) {
    ++T[ind].num;
    return;
  }
  int mid = (l + r) >> 1;
  ;
  pos <= mid ? add(T[ind].l, l, mid) : add(T[ind].r, mid + 1, r);
  pp(ind);
}
int join(int x, int y, int l, int r) {
  if (!(x && y)) return x ^ y;
  if (l == r) {
    T[x].num += T[y].num;
    return x;
  }
  int mid = (l + r) >> 1;
  ;
  T[x].l = join(T[x].l, T[y].l, l, mid);
  T[x].r = join(T[x].r, T[y].r, mid + 1, r);
  pp(x);
  return x;
}
void query(int ind, int l, int r) {
  if (ll <= l && r <= rr) {
    if (T[ind].num > ans1) ans1 = T[ind].num, ans2 = T[ind].mx;
    return;
  }
  int mid = (l + r) >> 1;
  ;
  if (ll <= mid) query(T[ind].l, l, mid);
  if (mid < rr) query(T[ind].r, mid + 1, r);
}
void append(int c) {
  int np = ++tot, p = la;
  maxlen[np] = maxlen[la] + 1;
  for (; p && !trans[p][c]; p = fa[p]) trans[p][c] = np;
  if (p) {
    int q = trans[p][c];
    if (maxlen[q] == maxlen[p] + 1) {
      if (maxlen[np] == maxlen[q]) {
        --tot;
        la = q;
        return;
      }
      fa[np] = q;
    } else {
      if (maxlen[np] == maxlen[p] + 1) {
        memcpy(trans[np], trans[q], sizeof(trans[q]));
        fa[np] = fa[q];
        fa[q] = np;
        for (; p && trans[p][c] == q; p = fa[p]) trans[p][c] = np;
        la = np;
        return;
      }
      int nq = ++tot;
      maxlen[nq] = maxlen[p] + 1;
      memcpy(trans[nq], trans[q], sizeof(trans[q]));
      fa[nq] = fa[q];
      fa[q] = fa[np] = nq;
      for (; p && trans[p][c] == q; p = fa[p]) trans[p][c] = nq;
    }
  } else
    trans[root][c] = np, fa[np] = root;
  la = np;
}
inline void read(int &x) {
  char ch = getchar();
  x = 0;
  while (ch < '0' || ch > '9') ch = getchar();
  while (ch >= '0' && ch <= '9')
    x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
}
char z[N], s[MM];
vector<int> son[TOT], g[TOT], u[N];
int as1[N], as2[N], xx[N], yy[N], aa[N], bb[N], l;
void dfs(int x) {
  for (auto i : son[x]) dfs(i), rt[x] = join(rt[x], rt[i], 1, m);
  for (auto i : g[x]) {
    ll = xx[i];
    rr = yy[i];
    ans1 = ans2 = 0;
    query(rt[x], 1, m);
    as1[i] = ans2;
    as2[i] = ans1;
  }
}
void walk(int c, int now) {
  int p = la;
  for (; p && !trans[p][c]; p = fa[p]) l = maxlen[fa[p]];
  if (!p) {
    p = root;
    l = 0;
  }
  p = trans[p][c];
  ++l;
  for (auto i : u[now]) {
    if (now - aa[i] + 1 > l) continue;
    int x = p;
    for (int j = 16; ~j; --j)
      if (maxlen[bz[x][j]] >= now - aa[i] + 1) x = bz[x][j];
    g[x].push_back(i);
  }
  la = p;
}
inline void write(int x) {
  if (x >= 10) write(x / 10);
  putchar('0' + x % 10);
}
int main() {
  scanf("%s%d", z + 1, &m);
  for (int i = 1; i <= m; ++i) {
    la = root;
    scanf("%s", s + 1);
    for (int j = 1; s[j]; ++j) {
      append(s[j] - 'a');
      pos = i;
      add(rt[la], 1, m);
    }
  }
  for (int i = 1; i <= tot; ++i) bz[i][0] = fa[i];
  for (int j = 1; j <= 16; ++j)
    for (int i = 1; i <= tot; ++i) bz[i][j] = bz[bz[i][j - 1]][j - 1];
  for (int i = 1; i <= tot; ++i) son[fa[i]].push_back(i);
  int qq;
  scanf("%d", &qq);
  for (int i = 1; i <= qq; ++i) {
    read(xx[i]);
    read(yy[i]);
    read(aa[i]);
    read(bb[i]);
    u[bb[i]].push_back(i);
  }
  la = root;
  l = 0;
  for (int i = 1; z[i]; ++i) walk(z[i] - 'a', i);
  dfs(root);
  for (int i = 1; i <= qq; ++i) {
    write(as2[i] ? as1[i] : xx[i]);
    putchar(' ');
    write(as2[i]);
    putchar('\n');
  }
}
