Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

文字列 S と， m 個のクエリが与えられる．i 番目のクエリは二つの文字列 xi, yi で与えられる．

各クエリについて，文字列 S の部分文字列であり， xi で始まり yi で終わるものの中で，最長の長さを答えよ．

文字列 S について， |S| は S の長さを表す．また，文字列 T が文字列 S の部分文字列であるとは，ある整数 i が存在して， 1 ≤ j ≤ |T| に対して Tj = Si+j を満たすことを言う．ただし Tj は T の j 番目の文字を表す．

Input

入力は以下の形式で与えられる．

S
m
x1 y1
x2 y2
:
xm ym

1 行目には，文字列 S が与えられる．

2 行目には，クエリの個数 m が与えられる．

3 行目からの m 行のうち i 行目には i 番目のクエリ文字列 xi, yi が空白区切りで与えられる．

Constraints

1 ≤ |S| ≤ 2 × 105

1 ≤ m ≤ 105

1 ≤ |xi|, |yi|

$\sum^m_{i=1}$ (|xi| + |yi|) ≤ 2 × 105

S 及び xi, yi は，半角の英小文字のみからなる．

Output

以下の形式で最大の部分文字列の長さを答えよ．

len1
len2
:
lenm

1 行目からの m 行のうち i 行目には， i 番目のクエリについて，条件を満たす最長の部分文字列の長さ leni を出力せよ．そのような部分文字列がない場合，0 を出力せよ．

Sample Input 1

abracadabra
5
ab a
a a
b c
ac ca
z z

Output for the Sample Input 1

11
11
4
3
0

文字列 S として，abracadabra が与えられる．

"ab" で始まり "a" で終わる部分文字列は，"abra" や "abraca", "abracada", "abracadabra" の4 種類があるが，最長の部分文字列は "abracadabra" で，長さは 11 である．

"a" で始まり "a" で終わる最長の部分文字列も同様に "abracadabra" で，長さは 11 である．

"b" で始まり "c" で終わる最長の部分文字列は "brac" で，長さは 4 である．

"ac" で始まり "ca" で終わる最長の部分文字列は "aca" で，長さは 3 である．

"z" で始まり "z" で終わる部分文字列は存在しない．よって0 を出力する．

Sample Input 2

howistheprogress
4
ist prog
s ss
how is
the progress

Output for the Sample Input 2

9
12
5
11

Sample Input 3

icpcsummertraining
9
mm m
icpc summer
train ing
summer mm
i c
i i
g g
train i
summer er

Output for the Sample Input 3

2
10
8
0
4
16
1
6
6

Solution in C++11 (judge verdict: Time Limit Exceeded)

#include <iostream>
#include <vector>
#include <algorithm>
#include <array>
#include <set>
#include <map>
#include <queue>
#include <tuple>
#include <unordered_set>
#include <unordered_map>
#include <functional>
#include <cstdio>
#include <cassert>
#define repeat(i,n) for (int i = 0; (i) < (n); ++(i))
#define repeat_from(i,m,n) for (int i = (m); (i) < (n); ++(i))
#define repeat_reverse(i,n) for (int i = (n)-1; (i) >= 0; --(i))
#define repeat_from_reverse(i,m,n) for (int i = (n)-1; (i) >= (m); --(i))
#define dump(x)  cerr << #x << " = " << (x) << endl
#define debug(x) cerr << #x << " = " << (x) << " (L" << __LINE__ << ")" << " " << __FILE__ << endl
typedef long long ll;
using namespace std;
vector<int> suffix_array(string const & s) { // O(nloglogn)
    int n = s.length();
    vector<int> sa(n+1);
    vector<int> rank(n+1);
    repeat (i,n+1) {
        sa[i] = i;
        rank[i] = i < n ? s[i] : -1;
    }
    for (int k = 1; k <= n; k *= 2) {
        auto compare = [&](int i, int j) {
            int ri = i + k <= n ? rank[i + k] : -1;
            int rj = j + k <= n ? rank[j + k] : -1;
            return make_pair(rank[i], ri) < make_pair(rank[j], rj);
        };
        sort(sa.begin(), sa.end(), compare);
        vector<int> dp(n+1);
        dp[sa[0]] = 0;
        repeat (i,n) dp[sa[i+1]] = dp[sa[i]] + compare(sa[i], sa[i+1]);
        rank = dp;
    }
    return sa;
}
int lower_bound(string const & s, vector<int> const & sa, string const & t) {
    int n = s.size();
    int l = 0, r = n+1;
    while (l + 1 < r) {
        int m = (l + r) / 2;
        (s.compare(sa[m], string::npos, t) < 0 ? l : r) = m;
    }
    return r;
}
int prefix_upper_bound(string const & s, vector<int> const & sa, string const & t) {
    int n = s.size();
    int l = 0, r = n+1;
    while (l + 1 < r) {
        int m = (l + r) / 2;
        (s.compare(sa[m], t.size(), t) <= 0 ? l : r) = m;
    }
    return r;
}
int main() {
    string s; cin >> s;
    vector<int> sa = suffix_array(s);
// cerr << "*** " << s << endl;
    int m; cin >> m;
    repeat (i,m) {
        string x, y; cin >> x >> y;
        int xl = lower_bound(s, sa, x);
        int xr = prefix_upper_bound(s, sa, x);
        int yl = lower_bound(s, sa, y);
        int yr = prefix_upper_bound(s, sa, y);
        int ans = 0;
// cerr << "* " << x << ' ' << y << endl;
        repeat_from (j,xl,xr) repeat_from (k,yl,yr) {
            if (sa[j] <= sa[k] and sa[j] + x.length() <= sa[k] + y.length()) {
// cerr << s.substr(sa[j],sa[k]-sa[j]+y.size()) << endl;
                ans = max(ans, sa[k]+int(y.size()) - sa[j]);
            }
        }
        cout << ans << endl;
    }
    return 0;
}