#include <bits/stdc++.h>
using namespace std;
namespace io {
const int L = (1 << 20) + 1;
char buf[L], *S, *T, c;
char getchar() {
  if (__builtin_expect(S == T, 0)) {
    T = (S = buf) + fread(buf, 1, L, stdin);
    return (S == T ? EOF : *S++);
  }
  return *S++;
}
int inp() {
  int x = 0, f = 1;
  char ch;
  for (ch = getchar(); !isdigit(ch); ch = getchar())
    if (ch == '-') f = -1;
  for (; isdigit(ch); x = x * 10 + ch - '0', ch = getchar())
    ;
  return x * f;
}
unsigned inpu() {
  unsigned x = 0;
  char ch;
  for (ch = getchar(); !isdigit(ch); ch = getchar())
    ;
  for (; isdigit(ch); x = x * 10 + ch - '0', ch = getchar())
    ;
  return x;
}
long long inp_ll() {
  long long x = 0;
  int f = 1;
  char ch;
  for (ch = getchar(); !isdigit(ch); ch = getchar())
    if (ch == '-') f = -1;
  for (; isdigit(ch); x = x * 10 + ch - '0', ch = getchar())
    ;
  return x * f;
}
char B[25], *outs = B + 20, *outr = B + 20;
template <class T>
inline void print(register T a, register char x = 0) {
  if (x) *--outs = x, x = 0;
  if (!a)
    *--outs = '0';
  else
    while (a) *--outs = (a % 10) + 48, a /= 10;
  if (x) *--outs = x;
  fwrite(outs, outr - outs, 1, stdout);
  outs = outr;
}
};  // namespace io
using io ::inp;
using io ::inp_ll;
using io ::inpu;
using io ::print;
using i32 = int;
using i64 = long long;
using u8 = unsigned char;
using u32 = unsigned;
using u64 = unsigned long long;
using f64 = double;
using f80 = long double;
long long power(long long a, long long b, long long p) {
  if (!b) return 1;
  long long t = power(a, b / 2, p);
  t = t * t % p;
  if (b & 1) t = t * a % p;
  return t;
}
long long gcd(long long a, long long b) { return b ? gcd(b, a % b) : a; }
template <class T>
inline void freshmin(T &a, const T &b) {
  if (a > b) a = b;
}
template <class T>
inline void freshmax(T &a, const T &b) {
  if (a < b) a = b;
}
const int MAXN = 400010;
const int MAXM = 26;
const int MOD = 1000000007;
const f80 MI = f80(1) / MOD;
const long long INF = 10000000000000000LL;
const long long inf = 5000000000000LL;
int n;
char s[MAXN];
int tot;
struct node {
  int dis;
  node *pre, *next[MAXM];
} sa[MAXN], *root;
node *new_node() { return &sa[++tot]; }
int vertex[MAXN];
void build_sa() {
  node *cur = root = new_node();
  for (int i = n; i >= 1; --i) {
    int x = s[i] - 'a';
    node *p = cur;
    cur = new_node();
    cur->dis = p->dis + 1;
    vertex[i] = cur - sa;
    for (; p && !p->next[x]; p = p->pre) p->next[x] = cur;
    if (!p)
      cur->pre = root;
    else {
      node *q = p->next[x];
      if (q->dis == p->dis + 1)
        cur->pre = q;
      else {
        node *r = new_node();
        *r = *q;
        r->dis = p->dis + 1;
        cur->pre = q->pre = r;
        for (; p && p->next[x] == q; p = p->pre) p->next[x] = r;
      }
    }
  }
}
vector<int> v[MAXN];
int size[MAXN], son[MAXN], father[MAXN], pre[MAXN], dis[MAXN];
void dfs1(int x) {
  size[x] = 1;
  if (v[x].empty()) return;
  for (auto y : v[x]) {
    dfs1(y);
    size[x] += size[y];
  }
  son[x] = *max_element(v[x].begin(), v[x].end(),
                        [&](int a, int b) { return size[a] < size[b]; });
}
void dfs2(int x) {
  if (!father[x]) father[x] = x;
  if (v[x].empty()) return;
  father[son[x]] = father[x];
  dfs2(son[x]);
  for (auto y : v[x])
    if (y != son[x]) dfs2(y);
}
void build_tree() {
  for (int i = 1; i <= tot; ++i) {
    pre[i] = sa[i].pre ? sa[i].pre - sa : 0;
    dis[i] = sa[i].dis;
    if (pre[i]) v[pre[i]].push_back(i);
  }
  dfs1(1);
  dfs2(1);
}
struct point {
  int no, len, pos;
};
vector<point> p[MAXN];
void make_vertex(int v) {
  int x = vertex[v];
  while (x > 1) {
    int y = father[x];
    p[y].push_back({v, dis[x] - dis[pre[y]], v + dis[pre[y]] + 1});
    x = pre[y];
  }
}
int q;
struct query {
  int id, len, bound;
  bool operator<(const query &A) const { return bound < A.bound; }
};
vector<query> q1[MAXN], q2[MAXN];
void make_query(int l, int len, int id) {
  int x = vertex[l];
  while (x > 1) {
    int y = father[x];
    if (dis[pre[y]] < len) {
      q1[y].push_back({id, min(dis[x], len) - dis[pre[y]], l - 1});
      q2[y].push_back({id, min(dis[x], len) - dis[pre[y]], l + len});
    }
    x = pre[y];
  }
}
int w[MAXN];
long long ww[MAXN];
void update(int p) {
  for (int x = p; x < MAXN; x += x & -x) {
    w[x] += 1;
    ww[x] += p;
  }
}
void resume(int x) {
  for (; x < MAXN; x += x & -x) ww[x] = w[x] = 0;
}
int getnum(int x) {
  int p = 0;
  for (; x; x -= x & -x) p += w[x];
  return p;
}
long long getsum(int x) {
  long long p = 0;
  for (; x; x -= x & -x) p += ww[x];
  return p;
}
long long ans[MAXN];
void solve(vector<point> &p, vector<query> &q1, vector<query> &q2) {
  if (p.empty()) return;
  if (!q1.empty()) {
    sort(p.begin(), p.end(),
         [](const point &a, const point &b) { return a.no < b.no; });
    sort(q1.begin(), q1.end());
    auto j = p.begin();
    int all = 0;
    for (auto i = q1.begin(); i != q1.end(); ++i) {
      for (; j != p.end() && j->no <= i->bound; ++j) {
        ++all;
        update(j->len);
      }
      int s = getnum(i->len);
      long long t = getsum(i->len);
      ans[i->id] -= (long long)i->len * (all - s) + t;
    }
    for (auto j = p.begin(); j != p.end(); ++j) resume(j->len);
  }
  if (!q2.empty()) {
    sort(p.begin(), p.end(), [](const point &a, const point &b) {
      return a.pos + a.len < b.pos + b.len;
    });
    sort(q2.begin(), q2.end());
    auto j = p.begin();
    int all = 0;
    for (auto i = q2.begin(); i != q2.end(); ++i) {
      for (; j != p.end() && j->pos + j->len <= i->bound + 1; ++j) {
        ++all;
        update(j->len);
      }
      int s = getnum(i->len);
      long long t = getsum(i->len);
      ans[i->id] += (long long)i->len * (all - s) + t;
    }
    for (auto j = p.begin(); j != p.end(); ++j) resume(j->len);
    reverse(p.begin(), p.end());
    reverse(q2.begin(), q2.end());
    j = p.begin();
    for (auto i = q2.begin(); i != q2.end(); ++i) {
      for (; j != p.end() && j->pos + j->len > i->bound + 1; ++j)
        update(j->pos);
      int s = getnum(i->bound);
      long long t = getsum(i->bound);
      if (i->bound - i->len + 1 <= 0)
        ans[i->id] += (long long)(i->bound + 1) * s - t;
      else {
        int s1 = getnum(i->bound - i->len + 1);
        long long t1 = getsum(i->bound - i->len + 1);
        ans[i->id] += (long long)i->len * s1 +
                      (long long)(i->bound + 1) * (s - s1) - (t - t1);
      }
    }
    for (auto j = p.begin(); j != p.end(); ++j) resume(j->pos);
  }
}
void solve() {
  for (int c = 1; c <= tot; ++c) {
    solve(p[c], q1[c], q2[c]);
  }
}
int main() {
  scanf("%s", s + 1);
  n = strlen(s + 1);
  build_sa();
  build_tree();
  for (int i = 1; i <= n; ++i) make_vertex(i);
  scanf("%d", &q);
  for (int i = 1; i <= q; ++i) {
    int x, y;
    scanf("%d%d", &x, &y);
    int len = y - x + 1;
    make_query(x, len, i);
  }
  solve();
  for (int i = 1; i <= q; ++i) printf("%lld\n", ans[i]);
  return 0;
}
