#include <bits/stdc++.h>
using namespace std;
int max(int a, int b) { return a > b ? a : b; }
int min(int a, int b) { return a < b ? a : b; }
struct Edge {
  int to, next;
} edge[50005 * 2];
int head[50005 * 2], tot;
void addedge(int from, int to) {
  edge[++tot].to = to;
  edge[tot].next = head[from];
  head[from] = tot;
}
struct Tree {
  Tree *l, *r;
  int maxnum, p;
  void update() {
    maxnum = 0;
    if (l) {
      maxnum = l->maxnum;
      p = l->p;
    }
    if (r) {
      if (r->maxnum > maxnum) {
        maxnum = r->maxnum;
        p = r->p;
      }
    }
  }
  void add(int k, int ll, int rr);
  void merge(Tree *c);
  pair<int, int> ask(int L, int R, int ll, int rr) {
    pair<int, int> ans;
    if (R < ll || rr < L) {
      ans.first = 0;
      ans.second = 0;
      return ans;
    }
    if (L <= ll && rr <= R) {
      ans.first = maxnum;
      ans.second = p;
      return ans;
    }
    pair<int, int> tmp;
    int mid = (ll + rr) >> 1;
    if (l == NULL) {
      return r->ask(L, R, mid + 1, rr);
    }
    if (r == NULL) {
      return l->ask(L, R, ll, mid);
    }
    ans = l->ask(L, R, ll, mid);
    tmp = r->ask(L, R, mid + 1, rr);
    if (ans.first >= tmp.first) {
      return ans;
    } else {
      return tmp;
    }
  }
} tree[50005 * 100], root[50005 * 2];
int treecnt;
Tree *getTree(Tree *copy) {
  ++treecnt;
  if (copy) {
    tree[treecnt] = *copy;
  }
  return &tree[treecnt];
}
void Tree::add(int k, int ll, int rr) {
  if (ll == rr) {
    ++maxnum;
    p = ll;
    return;
  }
  int mid = (ll + rr) >> 1;
  if (k <= mid) {
    if (l == NULL) {
      l = getTree(NULL);
    }
    l->add(k, ll, mid);
  } else {
    if (r == NULL) {
      r = getTree(NULL);
    }
    r->add(k, mid + 1, rr);
  }
  update();
}
void Tree::merge(Tree *c) {
  if (c->l) {
    if (l) {
      l = getTree(l);
      l->merge(c->l);
    } else {
      l = c->l;
    }
  }
  if (c->r) {
    if (r) {
      r = getTree(r);
      r->merge(c->r);
    } else {
      r = c->r;
    }
  }
  if (l == NULL && r == NULL) {
    maxnum += c->maxnum;
  } else {
    update();
  }
}
struct Node {
  int next[26], fa, len;
} node[50005 * 2];
int cnt = 1;
int add(int c, int last) {
  int p = last;
  int np = ++cnt;
  node[np] = node[0];
  node[np].len = node[p].len + 1;
  last = np;
  for (; p && node[p].next[c] == 0; p = node[p].fa) {
    node[p].next[c] = np;
  }
  if (p == 0) {
    node[np].fa = 1;
    return np;
  }
  int q = node[p].next[c];
  if (node[p].len + 1 == node[q].len) {
    node[np].fa = q;
    return np;
  }
  int nq = ++cnt;
  node[nq] = node[q];
  node[q].fa = nq;
  node[np].fa = nq;
  node[nq].len = node[p].len + 1;
  for (; p && node[p].next[c] == q; p = node[p].fa) {
    node[p].next[c] = nq;
  }
  return np;
}
struct T {
  int next[26], fa;
} ct[50005];
int Tcnt;
int insert(int now, char *str) {
  if (*str == 0) {
    return now;
  }
  if (ct[now].next[*str - 'a'] == 0) {
    ct[now].next[*str - 'a'] = ++Tcnt;
    ct[ct[now].next[*str - 'a']].fa = now;
  }
  return insert(ct[now].next[*str - 'a'], str + 1);
}
int f[50005 * 2][21];
void dfs(int now, int fa) {
  f[now][0] = fa;
  for (int i = 1; i <= 20; ++i) {
    f[now][i] = f[f[now][i - 1]][i - 1];
  }
  for (int i = head[now]; i; i = edge[i].next) {
    dfs(edge[i].to, now);
    root[now].merge(&root[edge[i].to]);
  }
}
char S[500005], str[50005];
int end3[50005], end2[500005], last[50005], lenth[500005];
int main() {
  scanf("%s", S + 1);
  int m;
  scanf("%d", &m);
  for (int i = 1; i <= m; ++i) {
    scanf("%s", str);
    end3[i] = insert(0, str);
  }
  queue<int> q;
  q.push(0);
  last[0] = 1;
  while (!q.empty()) {
    int now = q.front();
    q.pop();
    for (int i = 0; i < 26; ++i) {
      if (ct[now].next[i]) {
        q.push(ct[now].next[i]);
        last[ct[now].next[i]] = add(i, last[now]);
      }
    }
  }
  for (int i = 1; i <= m; ++i) {
    int now = end3[i];
    while (now) {
      root[last[now]].add(i, 0, 500005);
      now = ct[now].fa;
    }
  }
  int p = 1, len = 0;
  for (int i = 1; S[i]; ++i) {
    while (p != 1 && node[p].next[S[i] - 'a'] == 0) {
      p = node[p].fa;
      len = node[p].len;
    }
    if (node[p].next[S[i] - 'a']) {
      ++len;
      p = node[p].next[S[i] - 'a'];
    }
    end2[i] = p;
    lenth[i] = len;
  }
  for (int i = 2; i <= cnt; ++i) {
    addedge(node[i].fa, i);
  }
  dfs(1, 1);
  int n;
  scanf("%d", &n);
  int pl, pr, l, r;
  for (int i = 0; i < n; ++i) {
    scanf("%d%d%d%d", &l, &r, &pl, &pr);
    int p = end2[pr];
    for (int i = 20; i >= 0; --i) {
      if (node[f[p][i]].len >= pr - pl + 1) {
        p = f[p][i];
      }
    }
    if (lenth[pr] < pr - pl + 1) {
      printf("%d 0\n", l);
      continue;
    }
    pair<int, int> tmp = root[p].ask(l, r, 0, 500005);
    if (tmp.first == 0) {
      tmp.second = l;
    }
    printf("%d %d\n", tmp.second, tmp.first);
  }
}
