#include <bits/stdc++.h>
using std::abs;
using std::bitset;
using std::cerr;
using std::cin;
using std::copy;
using std::cout;
using std::deque;
using std::endl;
using std::fill;
using std::fixed;
using std::greater;
using std::istream;
using std::lower_bound;
using std::make_pair;
using std::make_tuple;
using std::map;
using std::max;
using std::max_element;
using std::min;
using std::min_element;
using std::multiset;
using std::next_permutation;
using std::nth_element;
using std::ostream;
using std::pair;
using std::priority_queue;
using std::queue;
using std::reverse;
using std::rotate;
using std::set;
using std::sort;
using std::string;
using std::swap;
using std::tie;
using std::tuple;
using std::unique;
using std::unordered_map;
using std::unordered_set;
using std::upper_bound;
using std::vector;
long long rnd(long long x, long long y) {
  static auto gen =
      std::bind(std::uniform_int_distribution<long long>(), std::mt19937(1510));
  return gen() % (y - x + 1) + x;
}
long long gcd(long long a, long long b) {
  while (b > 0) {
    int t = a % b;
    a = b;
    b = t;
  }
  return a;
}
int const INF = (int)1e9;
long long const INFL = (long long)1e18;
long double const PI = 3.1415926535897932384626433832795028;
int const N = 500500;
int const A = 26;
int const SQRT = 800;
int next_str(int* a) {
  static char buf[N];
  gets(buf);
  int len = 0;
  for (; buf[len]; ++len) {
    a[len] = buf[len] - 'a';
  }
  return len;
}
int tree_max[5 * N], tree_where[5 * N];
void build_tree(int v, int l, int r) {
  if (r - l > 1) {
    int m = (l + r) / 2;
    build_tree(2 * v + 1, l, m);
    build_tree(2 * v + 2, m, r);
  }
  tree_max[v] = 0;
  tree_where[v] = l;
}
void modify(int v, int l, int r, int pos, int add) {
  if (pos < 0) {
    return;
  }
  if (r - l == 1) {
    tree_max[v] += add;
  } else {
    int m = (l + r) / 2;
    if (pos < m) {
      modify(2 * v + 1, l, m, pos, add);
    } else {
      modify(2 * v + 2, m, r, pos, add);
    }
    tree_max[v] = max(tree_max[2 * v + 1], tree_max[2 * v + 2]);
    tree_where[v] = tree_max[v] == tree_max[2 * v + 1] ? tree_where[2 * v + 1]
                                                       : tree_where[2 * v + 2];
  }
}
int tree_count, tree_index;
void get_max(int v, int l, int r, int from, int to) {
  if (to <= l || r <= from) {
    return;
  }
  if (from <= l && r <= to) {
    if (tree_max[v] > tree_count) {
      tree_count = tree_max[v];
      tree_index = tree_where[v];
    }
    return;
  }
  int m = (l + r) / 2;
  get_max(2 * v + 1, l, m, from, to);
  get_max(2 * v + 2, m, r, from, to);
}
int sa_n;
int sa[N + N];
int where[N + N];
int lcp[21][N + N];
int deg[N + N];
void build_sa(int* s, int n) {
  static int start[N + N], new_sa[N + N], cl[N + N], new_cl[N + N];
  sa_n = n;
  fill(start, start + N + N, 0);
  for (int i = 0; i < n; ++i) ++start[s[i] + 1];
  for (int i = 1; i < N + N; ++i) start[i] += start[i - 1];
  for (int i = 0; i < n; ++i) sa[start[s[i]]++] = i;
  copy(s, s + n, cl);
  fill(start, start + N + N, 0);
  for (int i = 0; i < n; ++i) ++start[s[i] + 1];
  for (int i = 1; i < N + N; ++i) start[i] += start[i - 1];
  for (int half = 1; half < n; half *= 2) {
    for (int i = 0; i < n; ++i) {
      sa[i] -= half;
      if (sa[i] < 0) sa[i] += n;
    }
    for (int i = 0; i < n; ++i) new_sa[start[cl[sa[i]]]++] = sa[i];
    new_cl[new_sa[0]] = 0;
    start[0] = 0;
    int sz = 1;
    for (int i = 0; i + 1 < n; ++i) {
      int j = i + 1;
      int ni = new_sa[i] + half;
      if (ni >= n) ni -= n;
      int nj = new_sa[j] + half;
      if (nj >= n) nj -= n;
      if (cl[new_sa[i]] != cl[new_sa[j]] || cl[ni] != cl[nj]) {
        start[sz] = j;
        new_cl[new_sa[j]] = sz++;
      } else {
        new_cl[new_sa[j]] = new_cl[new_sa[i]];
      }
    }
    copy(new_sa, new_sa + n, sa);
    copy(new_cl, new_cl + n, cl);
  }
  for (int i = 0; i < n; ++i) where[sa[i]] = i;
  for (int last = 0, i = 0; i < n; ++i) {
    if (last > 0) --last;
    if (where[i] == n - 1) {
      last = 0;
      continue;
    }
    int j = sa[where[i] + 1];
    while (i + last < n && j + last < n && s[i + last] == s[j + last]) ++last;
    lcp[0][where[i]] = last;
  }
  --n;
  for (int i = 1; (1 << i) <= n; ++i) {
    int len = 1 << i;
    for (int j = 0; j + len <= n; ++j) {
      lcp[i][j] = min(lcp[i - 1][j], lcp[i - 1][j + len / 2]);
    }
  }
  for (int i = 2; i <= n; ++i) deg[i] = deg[i / 2] + 1;
}
int get_lcp(int i, int j) {
  if (i == j) return sa_n - sa[i];
  if (i > j) std::swap(i, j);
  int lb = deg[j - i];
  return std::min(lcp[lb][i], lcp[lb][j - (1 << lb)]);
}
void solve() {
  static int s[N + N];
  static int color[N + N];
  int slen = next_str(s);
  int n;
  scanf("%d ", &n);
  int sz = 0;
  fill(color, color + slen, -1);
  sz += slen;
  s[sz] = A;
  color[sz++] = -1;
  for (int i = 0; i < n; i++) {
    int cur_len = next_str(s + sz);
    fill(color + sz, color + sz + cur_len, i);
    sz += cur_len;
    s[sz] = A + i + 1;
    color[sz++] = -1;
  }
  build_sa(s, sz);
  int m;
  scanf("%d", &m);
  struct Query {
    int l, r, p_l, p_r, sa_l, sa_r;
    int ind;
    void find_range() {
      int pos = where[p_l];
      int l = -1, r = pos;
      while (r - l > 1) {
        int m = (l + r) / 2;
        if (get_lcp(m, pos) >= p_r - p_l) {
          r = m;
        } else {
          l = m;
        }
      }
      sa_l = r;
      l = pos - 1, r = sa_n;
      while (r - l > 1) {
        int m = (l + r) / 2;
        if (get_lcp(m, pos) >= p_r - p_l) {
          l = m;
        } else {
          r = m;
        }
      }
      sa_r = r;
    }
  };
  static Query qs[N];
  for (int i = 0; i < m; i++) {
    scanf("%d%d%d%d", &qs[i].l, &qs[i].r, &qs[i].p_l, &qs[i].p_r);
    --qs[i].l;
    --qs[i].p_l;
    qs[i].find_range();
    qs[i].ind = i;
  }
  sort(qs, qs + m, [](Query const& q1, Query const& q2) {
    if (q1.sa_l / SQRT != q2.sa_l / SQRT) {
      return q1.sa_l < q2.sa_l;
    }
    return q1.sa_r < q2.sa_r;
  });
  int L = 0, R = 0;
  build_tree(0, 0, n);
  static int text_index[N], count[N];
  for (int i = 0; i < m; ++i) {
    Query& q = qs[i];
    while (R < q.sa_r) modify(0, 0, n, color[sa[R++]], 1);
    while (L > q.sa_l) modify(0, 0, n, color[sa[--L]], 1);
    while (R > q.sa_r) modify(0, 0, n, color[sa[--R]], -1);
    while (L < q.sa_l) modify(0, 0, n, color[sa[L++]], -1);
    tree_count = -1;
    tree_index = -1;
    get_max(0, 0, n, q.l, q.r);
    count[q.ind] = tree_count;
    text_index[q.ind] = tree_index;
  }
  for (int i = 0; i < m; ++i) {
    printf("%d %d\n", text_index[i] + 1, count[i]);
  }
}
int main() {
  cout.precision(15);
  cout << fixed;
  cerr.precision(6);
  cerr << fixed;
  solve();
}
