Problem:
文字列
S
と，
m
個のクエリが与えられる．
i
番目のクエリは二つの文字列
x
i
, y
i
で与えられる．
各クエリについて，文字列
S
の部分文字列であり，
x
i
で始まり
y
i
で終わるものの中で，最長の長さを答えよ．
文字列
S
について，
|S|
は
S
の長さを表す．また，文字列
T
が文字列
S
の部分文字列であるとは，ある整数
i
が存在して， 1 ≤
j
≤
|T|
に対して
T
j
= S
i+j
を満たすことを言う．ただし
T
j
は
T
の
j
番目の文字を表す．
Input
入力は以下の形式で与えられる．
S
m
x
1
y
1
x
2
y
2
:
x
m
y
m
1 行目には，文字列
S
が与えられる．
2 行目には，クエリの個数
m
が与えられる．
3 行目からの
m
行のうち
i
行目には
i
番目のクエリ文字列
x
i
, y
i
が空白区切りで与えられる．
Constraints
1 ≤
|S|
≤ 2 × 10
5
1 ≤
m
≤ 10
5
1 ≤
|x
i
|, |y
i
|
$\sum^m_{i=1}$ (
|x
i
| + |y
i
|
) ≤ 2 × 10
5
S
及び
x
i
, y
i
は，半角の英小文字のみからなる．
Output
以下の形式で最大の部分文字列の長さを答えよ．
len
1
len
2
:
len
m
1 行目からの
m
行のうち
i
行目には，
i
番目のクエリについて，条件を満たす最長の部分文字列の長さ
len
i
を出力せよ．そのような部分文字列がない場合，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

Submitted solutions:

code_snippet: #include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<ll, ll> P;

#define each(i,a) for (auto&& i : a)
#define FOR(i,a,b) for (ll i=(a),__last_##i=(b);i<__last_##i;i++)
#define RFOR(i,a,b) for (ll i=(b)-1,__last_##i=(a);i>=__last_##i;i--)
#define REP(i,n) FOR(i,0,n)
#define RREP(i,n) RFOR(i,0,n)
#define __GET_MACRO3(_1, _2, _3, NAME, ...) NAME
#define rep(...) __GET_MACRO3(__VA_ARGS__, FOR, REP)(__VA_ARGS__)
#define rrep(...) __GET_MACRO3(__VA_ARGS__, RFOR, RREP)(__VA_ARGS__)
#define pb push_back
#define all(a) (a).begin(),(a).end()
#define chmin(x,v) x = min(x, v)
#define chmax(x,v) x = max(x, v)

const ll linf = 1e18;
const double eps = 1e-12;
const double pi = acos(-1);

template<typename T>
istream& operator>>(istream& is, vector<T>& vec) {
    each(x,vec) is >> x;
    return is;
}
template<typename T>
ostream& operator<<(ostream& os, const vector<T>& vec) {
    rep(i,vec.size()) {
        if (i) os << " ";
        os << vec[i];
    }
    return os;
}
template<typename T>
ostream& operator<<(ostream& os, const vector< vector<T> >& vec) {
    rep(i,vec.size()) {
        if (i) os << endl;
        os << vec[i];
    }
    return os;
}

class SuffixArray {
    const ll n;
    const string str;
    vector<ll> sa, lcp;
public:
    SuffixArray(const string& s) : str(s), n(s.size()) {}
    vector<ll> make_sa() {
        sa.assign(n+1, 0);
        rep(i, n+1) sa[i] = i;
        vector<ll> rank(all(str));
        rank.pb(-1);
        auto f = [&](ll idx, ll len) {
            return idx + len <= n ? rank[idx+len] : -1;
        };
        for (ll k = 1; k <= n; k <<= 1) {
            auto compare = [&](ll a, ll b) {
                if (rank[a] != rank[b]) return rank[a] < rank[b];
                else return f(a, k) < f(b, k);
            };
            sort(all(sa), compare);
            vector<ll> nrank(n+1, 0);
            rep(i, 1, n+1) {
                nrank[sa[i]] = nrank[sa[i-1]] + compare(sa[i-1], sa[i]);
            }
            rank = nrank;
        }
        return sa;
    }
    vector<ll> make_lcp() {
        assert(sa.size() > 0);
        lcp.assign(sa.size(), 0);
        vector<ll> rank(n+1);
        rep(i, n+1) rank[sa[i]] = i;
        ll h = 0;
        rep(i, n) {
            if (h > 0) --h;
            assert(rank[i] > 0);
            for (ll j = sa[rank[i]-1]; j + h < n && i + h < n; h++) {
                if (str[j+h] != str[i+h]) break;
            }
            lcp[rank[i]-1] = h;
        }
        return lcp;
    }
    P search(const string& s) {
        assert(lcp.size() > 0);
        ll l = -1, r = -1;
        {
            ll lb = 0, ub = n+1;
            while (ub - lb > 1) {
                ll mid = (lb + ub) / 2;
                if (str.substr(sa[mid], s.size()) >= s) {
                    ub = mid;
                }
                else {
                    lb = mid;
                }
            }
            l = ub;
        }
        {
            ll lb = 0, ub = n+1;
            while (ub - lb > 1) {
                ll mid = (lb + ub) / 2;
                if (str.substr(sa[mid], s.size()) > s) {
                    ub = mid;
                }
                else {
                    lb = mid;
                }
            }
            r = ub;
        }
        return P(l, r);
    }
};
class SegmentManager {
    ll len;
    set<P> s;
    ll length(const P& p) {
        return p.second - p.first;
    }
    set<P>::iterator erase(const set<P>::iterator it) {
        len -= length(*it);
        return s.erase(it);
    }
    void insert(const P& p) {
        len += length(p);
        s.insert(p);
    }
    set<P>::iterator lb(ll l) {
        return s.lower_bound({l, l});
    }
    set<P>::iterator ub(ll l) {
        return lb(l+1);
    }
public:
    SegmentManager() : len(0) {}
    void add(ll l, ll r) {
        if (r <= l) return;
        erase(l, r);
        // merge right
        {
            auto it = lb(r);
            if (it != s.end() && it->first == r) {
                r = it->second;
                erase(it);
            }
        }
        // merge left
        {
            auto it = lb(l);
            if (it != s.begin()) {
                --it;
                if (it->second == l) {
                    l = it->first;
                    erase(it);
                }
            }
        }
        // add
        insert({l, r});
    }
    void erase(ll l, ll r) {
        if (r <= l) return;
        // cut left
        {
            auto it = lb(l);
            if (it != s.begin()) {
                --it;
                if (it->second > l) {
                    insert({it->first, l});
                    if (it->second > r) {
                        insert({r, it->second});
                        erase(it);
                        return;
                    }
                    erase(it);
                }
            }
        }
        auto it = lb(l);
        auto itr = lb(r);
        while (it != itr) {
            if (it->second > r) {
                insert({r, it->second});
                it = erase(it);
                break;
            }
            it = erase(it);
        }
    }
    bool is_in(ll l, ll r) {
        assert(r >= l);
        auto it = ub(l);
        if (it == s.begin()) return false;
        --it;
        return it->first <= l && r <= it->second;
    }
    bool is_in(ll pos) { return is_in(pos, pos+1); }
    ll length() { return len; }
    ll count() { return s.size(); }
    void out() {
        each(p, s) {
            cout << "[" << p.first << ", " << p.second << ")" << endl;
        }
    }
};
// SegmentTree<int> seg(n, 0x7FFFFFFF, [](int a, int b){return min(a, b);});
template <class T>
class SegmentTree {
    using func_t = function<T(T, T)>;
    const int sz, n;
    const T id;
    func_t merge;
    vector<T> data;
    int expand(int n) const { return n == 1 ? n : expand((n + 1) / 2) * 2; }
public:
    SegmentTree(const vector<T> &init, T id, func_t merge) :
        sz(init.size()), n(expand(sz)), id(id), data(n * 2, id), merge(merge) {
        copy(begin(init), end(init), begin(data)+n);
        RREP(i, n) {
            data[i] = merge(data[i * 2 + 0], data[i * 2 + 1]);
        }
    }
    int size() const { return sz; }
    void update(int p, T val) {
        assert (0 <= p && p < sz);
        data[p += n] = val;
        while (p /= 2) data[p] = merge(data[p * 2], data[p * 2 + 1]);
    }
    T find(int l, int r) const {
        assert (0 <= l && l <= r && r <= sz);
        l += n; r += n;
        T res1 = id, res2 = id;
        while (l != r) {
            if (l % 2) res1 = merge(res1, data[l++]);
            if (r % 2) res2 = merge(data[--r], res2);
            l /= 2; r /= 2;
        }
        return merge(res1, res2);
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    string S; cin >> S;
    SuffixArray Sa(S);
    vector<ll> sa = Sa.make_sa();
    vector<ll> lcp = Sa.make_lcp();
    SegmentTree<ll> rmq(sa, linf, [](ll a, ll b) { return min(a, b); });
    SegmentTree<ll> rMq(sa, -linf, [](ll a, ll b) { return max(a, b); });
    ll Q; cin >> Q;
    rep(q, Q) {
        string s1, s2; cin >> s1 >> s2;
        P p1 = Sa.search(s1);
        P p2 = Sa.search(s2);
        if (p1.second <= p1.first || p2.second <= p2.first) {
            cout << 0 << endl;
        }
        else {
            ll l = rmq.find(p1.first, p1.second);
            ll r = rMq.find(p2.first, p2.second);
            // cout << l << " " << r << endl;
            if (r < l) cout << 0 << endl;
            else {
                ll ans = r+s2.size()-l;
                if (ans < s1.size()) cout << 0 << endl;
                else cout << ans << endl;
            }
        }
    }
}
accuracy: 1
time_ms: 260
memory_kb: 19540
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

const long long mod = 1929318247;
const int CONST = 71;
int N;
long long Hash[200009];
long long Powr[200009];
pair<int, int> List[CONST + 3][200009];

long long get_hash(string S) {
    long long r = 0;
    for (int i = 0; i < S.size(); i++) {
        r = (283LL * r + 1LL + (long long)(S[i] - 'a')) % mod;
    }
    return r;
}

int find_value_left(string S) {
    if (S.size() > N) return (1 << 30);
    int base = get_hash(S);

    // Casework
    if (S.size() <= CONST) {
        int pos = lower_bound(List[S.size()], List[S.size()] + (N - S.size() + 1), make_pair(base, 0)) - List[S.size()];
        if (pos < N - S.size() + 1 && List[S.size()][pos].first == base) {
            return List[S.size()][pos].second;
        }
        return (1 << 30);
    }
    else {
        for (int i = 0; i <= N - (int)S.size(); i++) {
            long long hashval = (Hash[i + S.size()] - Hash[i] * Powr[S.size()] + mod * mod) % mod;
            if (hashval == 1LL * base) return i;
        }
        return (1 << 30);
    }
}

int find_value_right(string S) {
    if (S.size() > N) return -1;
    int base = get_hash(S);

    // Casework
    if (S.size() <= CONST) {
        int pos = lower_bound(List[S.size()], List[S.size()] + (N - S.size() + 1), make_pair(base, 10000000)) - List[S.size()];
        pos--;
        if (pos >= 0 && List[S.size()][pos].first == base) {
            return List[S.size()][pos].second;
        }
        return -1;
    }
    else {
        for (int i = N - (int)S.size(); i >= 0; i--) {
            long long hashval = (Hash[i + S.size()] - Hash[i] * Powr[S.size()] + mod * mod) % mod;
            if (hashval == 1LL * base) return i;
        }
        return -1;
    }
}

int main() {
    // Step 1. Input
    string S; cin >> S; N = S.size();
    int Q; cin >> Q;
    vector<string> X(Q, "");
    vector<string> Y(Q, "");
    for (int i = 0; i < Q; i++) cin >> X[i] >> Y[i];

    // Step 2. Get Hash
    Powr[0] = 1;
    for (int i = 1; i <= S.size(); i++) Powr[i] = (283LL * Powr[i - 1]) % mod;
    for (int i = 1; i <= S.size(); i++) Hash[i] = (283LL * Hash[i - 1] + 1LL + (long long)(S[i - 1] - 'a')) % mod;

    // Step 3. Get List
    for (int i = 1; i <= min(N, CONST); i++) {
        for (int j = 0; j <= N - i; j++) {
            long long val = (Hash[i + j] - Hash[j] * Powr[i] + mod * mod) % mod;
            List[i][j] = make_pair((int)val, j);
        }
        sort(List[i], List[i] + (N - i + 1));
        /*for (int j = 0; j <= N - i + 1; j++) cout << "(" << List[i][j].first << ", " << List[i][j].second << ") ";
        cout << endl;*/
    }

    // Step 4. Answer Query
    for (int i = 0; i < Q; i++) {
        int ans_left = find_value_left(X[i]);
        int ans_rigt = find_value_right(Y[i]);
        int offset_min = max(0, (int)X[i].size() - (int)Y[i].size());
        // cerr << ans_left << " " << ans_rigt << endl;
        if (ans_left + offset_min <= ans_rigt) {
            cout << ans_rigt - ans_left + Y[i].size() << endl;
        }
        else {
            cout << "0" << endl;
        }
    }
    return 0;
}
accuracy: 1
time_ms: 710
memory_kb: 124908
final_rank: 17

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

template<typename T>struct SuffixArray{
    T base;
    vector<int> sa,rsa,lcp;
    SuffixArray(const T& _s):base(_s){
        int n=base.size();
        auto p=minmax_element(ALL(base));
        int k=*p.second-*p.first+1;
        vector<int> t(n);
        rep(i,0,n)t[i]=base[i]-*p.first;
        sais(t,k);
        rsa.assign(n+1,-1);
        rep(i,0,n+1)rsa[sa[i]]=i;
        build(t);
    }
    void sais(vector<int> s,int k){
        int n=s.size();
        for(int& c:s)c++;
        s.push_back(0);
        k++;
        vector<bool> iss(n+1);
        vector<int> lms,bin(k+1,0);
        iss[n]=1;
        bin[1]=1;
        for(int i=n-1;i>=0;i--){
            iss[i]=(s[i]!=s[i+1]?s[i]<s[i+1]:iss[i+1]);
            if(!iss[i]&&iss[i+1])lms.push_back(i+1);
            bin[s[i]+1]++;
        }
        rep(i,0,k)bin[i+1]+=bin[i];
        auto induced=[&](const vector<int>& _lms)->void{
            sa.assign(n+1,-1);
            vector<int> cnt(k,0);
            for(int x:_lms){
                sa[bin[s[x]+1]-cnt[s[x]]-1]=x;
                cnt[s[x]]++;
            }
            cnt.assign(k,0);
            rep(i,0,n+1){
                int x=sa[i]-1;
                if(x>=0&&!iss[x]){
                    sa[bin[s[x]]+cnt[s[x]]]=x;
                    cnt[s[x]]++;
                }
            }
            cnt.assign(k,0);
            for(int i=n;i>=0;i--){
                int x=sa[i]-1;
                if(x>=0&&iss[x]){
                    sa[bin[s[x]+1]-cnt[s[x]]-1]=x;
                    cnt[s[x]]++;
                }
            }
        };
        induced(lms);
        if(lms.size()<=1)return;
        int m=lms.size();
        vector<int> rev(n+1,-1);
        rep(i,0,m)rev[lms[i]]=i;
        int idx=0,rec_k=1;
        vector<int> lmss(m),rec_s(m);
        for(int x:sa)if(rev[x]!=-1)lmss[idx++]=x;
        rec_s[m-1-rev[lmss[1]]]=1;
        rep(i,2,m){
            int xl=lmss[i],yl=lmss[i-1];
            int xr=lms[rev[xl]-1],yr=lms[rev[yl]-1];
            if(xr-xl!=yr-yl)rec_k++;
            else while(xl<=xr){
                if(s[xl]!=s[yl]){
                    rec_k++;
                    break;
                }
                xl++,yl++;
            }
            rec_s[m-1-rev[lmss[i]]]=rec_k;
        }
        sais(rec_s,rec_k+1);
        idx=m;
        rep(i,1,m+1)lmss[--idx]=lms[m-1-sa[i]];
        induced(lmss);
    }
    void build(const vector<int>& s){
        int n=s.size(),k=0;
        lcp.resize(n);
        rep(i,0,n+1){
            if(rsa[i]){
                for(int j=sa[rsa[i]-1];max(i,j)+k<n;k++){
                    if(s[i+k]!=s[j+k])break;
                }
                lcp[rsa[i]-1]=k;
            }
            if(k)k--;
        }
    }
    array<int,2> search(const T& t){
        int n=sa.size(),m=t.size();
        array<int,2> ret;
        int L=0,R=n;
        while(R-L>1){
            int mid=(L+R)>>1;
            if(base.compare(sa[mid],m,t)<0)L=mid;
            else R=mid;
        }
        ret[0]=R;
        L=0,R=n;
        while(R-L>1){
            int mid=(L+R)>>1;
            if(base.compare(sa[mid],m,t)<=0)L=mid;
            else R=mid;
        }
        ret[1]=R;
        return ret;
    }
};

/**
 * @brief Suffix Array
 */

template <typename M, typename N, M (*f)(M, M), M (*g)(M, N), M (*m1)()>
struct SegmentTree {
    int sz, n;
    vector<M> data;
    SegmentTree(int _n = 0) : n(_n) {
        sz = 1;
        while (sz < _n)
            sz <<= 1;
        data.assign(2 * sz, m1());
    }
    void run(vector<M> &v) {
        for (int i = 0; i < (int)v.size(); i++)
            data[i + sz] = v[i];
        for (int k = sz - 1; k > 0; k--)
            data[k] = f(data[2 * k], data[2 * k + 1]);
    }
    void set(int k, const M &x) {
        k += sz;
        data[k] = x;
        while (k >>= 1)
            data[k] = f(data[2 * k], data[2 * k + 1]);
    }
    void update(int k, const N &x) {
        k += sz;
        data[k] = g(data[k], x);
        while (k >>= 1)
            data[k] = f(data[2 * k], data[2 * k + 1]);
    }
    M query(int a, int b) {
        M L = m1(), R = m1();
        for (a += sz, b += sz; a < b; a >>= 1, b >>= 1) {
            if (a & 1)
                L = f(L, data[a++]);
            if (b & 1)
                R = f(data[--b], R);
        }
        return f(L, R);
    }
    M operator[](const int &k) const {
        return data[k + sz];
    }
    vector<M> get() {
        return {data.begin() + sz, data.begin() + sz + n};
    }
    template <class F> int max_right(int L, F ch) const {
        int l = sz + L, w = 1;
        M ansL = m1();
        for (; L + w <= sz; l >>= 1, w <<= 1)
            if (l & 1) {
                if (not ch(f(ansL, data[l])))
                    break;
                ansL = f(ansL, data[l++]);
                L += w;
            }
        while (l <<= 1, w >>= 1) {
            if (L + w <= sz && ch(f(ansL, data[l]))) {
                ansL = f(ansL, data[l++]);
                L += w;
            }
        }
        return L;
    }
    template <class F> int min_left(int R, F ch) const {
        int r = sz + R, w = 1;
        M ansR = m1();
        for (; R - w >= 0; r >>= 1, w <<= 1)
            if (r & 1) {
                if (not ch(f(data[r - 1], ansR)))
                    break;
                ansR = f(data[--r], ansR);
                R -= w;
            }
        while (r <<= 1, w >>= 1) {
            if (R - w >= 0 && ch(f(data[r - 1], ansR))) {
                ansR = f(data[--r], ansR);
                R -= w;
            }
        }
        return R;
    }
};

/**
 * @brief Segment Tree
 */

int f(int A, int B) {return min(A,B);}
int g(int A, int B) {return min(A,B);}
int e() {return inf;}

int main() {
    string S;
    int Q;
    cin >> S >> Q;
    int N = S.size();
    SuffixArray SA(S);
    SegmentTree<int,int,f,g,e> SegS(SA.sa.size());
    SegS.run(SA.sa);
    string T = S;
    reverse(ALL(T));
    SuffixArray TA(T);
    SegmentTree<int,int,f,g,e> SegT(TA.sa.size());
    SegT.run(TA.sa);
    while(Q--) {
        string X, Y;
        cin >> X >> Y;
        auto [SL,SR] = SA.search(X);
        if (SL == SR) {
            cout << 0 << endl;
            continue;
        }
        int L = SegS.query(SL,SR);
        reverse(ALL(Y));
        auto [TL,TR] = TA.search(Y);
        if (TL == TR) {
            cout << 0 << endl;
            continue;
        }
        int R = SegT.query(TL,TR);
        R = N - R;
        int ANS = R - L;
        if (ANS >= (int)max(X.size(), Y.size())) cout << ANS << endl;
        else cout << 0 << endl;
    }
}
accuracy: 1
time_ms: 130
memory_kb: 16712
final_rank: 3

code_snippet: #pragma region Macros

#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,fma,abm,mmx,avx,avx2")

#include <bits/extc++.h>
// #include <atcoder/all>
// using namespace atcoder;
using namespace std;
using namespace __gnu_pbds;

// #include <boost/multiprecision/cpp_dec_float.hpp>
// #include <boost/multiprecision/cpp_int.hpp>
// namespace mp = boost::multiprecision;
// using Bint = mp::cpp_int;
// using Bdouble = mp::number<mp::cpp_dec_float<256>>;
// Bdouble Beps = 0.00000000000000000000000000000001; // 1e-32
// const bool equals(Bdouble a, Bdouble b) { return mp::fabs(a - b) < Beps; }

#define pb emplace_back
// #define int ll
#define endl '\n'
// #define unordered_map<int, int> gp_hash_table<int, int, custom_hash> 

#define sqrt __builtin_sqrtl
#define cbrt __builtin_cbrtl
#define hypot __builtin_hypotl

#define next asdnext
#define prev asdprev

using ll = long long;
using ld = long double;
const ld PI = acosl(-1);
const int INF = 1 << 30;
const ll INFL = 1LL << 61;
// const int MOD = 998244353;
const int MOD = 1000000007;

const ld EPS = 1e-10;
const bool equals(ld a, ld b) { return fabs((a) - (b)) < EPS; }

const vector<int> dx = {0, 1, 0, -1, 1, 1, -1, -1}; // → ↓ ← ↑ ↘ ↙ ↖ ↗
const vector<int> dy = {1, 0, -1, 0, 1, -1, -1, 1};

#define EC int
struct Edge {
    int from, to;
    EC cost;
    Edge() : from(-1), to(-1), cost(-1) {}
    Edge(int to, EC cost) : to(to), cost(cost) {}
    Edge(int from, int to, EC cost) : from(from), to(to), cost(cost) {}
    bool operator ==(const Edge& e) {
        return this->from == e.from && this->to == e.to && this->cost == e.cost;
    }
    bool operator !=(const Edge& e) {
        return this->from != e.from or this->to != e.to or this->cost != e.cost;
    }
    bool operator <(const Edge& e) { return this->cost < e.cost; }
    bool operator >(const Edge& e) { return this->cost > e.cost; }
};

chrono::system_clock::time_point start;
__attribute__((constructor))
void constructor() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(10);
    start = chrono::system_clock::now();
}

int ceil(int x, int y) { // (ld)x / y 以上の最小の整数
    assert(y != 0);
    if (y < 0) x = -x, y = -y;
    return x > 0 ? (x - 1) / y + 1 : x / y;
}

#pragma endregion

unsigned _bit_ceil(unsigned n) {
    unsigned x = 1;
    while (x < (unsigned)(n)) x *= 2;
    return x;
}

int _countr_zero(unsigned n) {
    return __builtin_ctz(n);
}

template <class S, S (*op)(S, S), S (*e)()> struct segtree {
public:
    segtree() : segtree(0) {}
    explicit segtree(int n) : segtree(vector<S>(n, e())) {}
    explicit segtree(const vector<S>& v) : _n(int(v.size())) {
        size = (int)_bit_ceil((unsigned int)(_n));
        log = _countr_zero((unsigned int)size);
        d = vector<S>(2 * size, e());
        for (int i = 0; i < _n; i++) d[size + i] = v[i];
        for (int i = size - 1; i >= 1; i--) {
            update(i);
        }
    }

    void set(int p, S x) {
        assert(0 <= p && p < _n);
        p += size;
        d[p] = x;
        for (int i = 1; i <= log; i++) update(p >> i);
    }

    S get(int p) const {
        assert(0 <= p && p < _n);
        return d[p + size];
    }

    S prod(int l, int r) const {
        assert(0 <= l && l <= r && r <= _n);
        S sml = e(), smr = e();
        l += size;
        r += size;

        while (l < r) {
            if (l & 1) sml = op(sml, d[l++]);
            if (r & 1) smr = op(d[--r], smr);
            l >>= 1;
            r >>= 1;
        }
        return op(sml, smr);
    }

    S all_prod() const { return d[1]; }

    template <bool (*f)(S)> int max_right(int l) const {
        return max_right(l, [](S x) { return f(x); });
    }
    template <class F> int max_right(int l, F f) const {
        assert(0 <= l && l <= _n);
        assert(f(e()));
        if (l == _n) return _n;
        l += size;
        S sm = e();
        do {
            while (l % 2 == 0) l >>= 1;
            if (!f(op(sm, d[l]))) {
                while (l < size) {
                    l = (2 * l);
                    if (f(op(sm, d[l]))) {
                        sm = op(sm, d[l]);
                        l++;
                    }
                }
                return l - size;
            }
            sm = op(sm, d[l]);
            l++;
        } while ((l & -l) != l);
        return _n;
    }

    template <bool (*f)(S)> int min_left(int r) const {
        return min_left(r, [](S x) { return f(x); });
    }
    template <class F> int min_left(int r, F f) const {
        assert(0 <= r && r <= _n);
        assert(f(e()));
        if (r == 0) return 0;
        r += size;
        S sm = e();
        do {
            r--;
            while (r > 1 && (r % 2)) r >>= 1;
            if (!f(op(d[r], sm))) {
                while (r < size) {
                    r = (2 * r + 1);
                    if (f(op(d[r], sm))) {
                        sm = op(d[r], sm);
                        r--;
                    }
                }
                return r + 1 - size;
            }
            sm = op(d[r], sm);
        } while ((r & -r) != r);
        return 0;
    }

private:
    int _n, size, log;
    vector<S> d;

    void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
};


namespace internal {

vector<int> sa_naive(const vector<int> &s) {
    int n = int(s.size());
    vector<int> sa(n);
    iota(sa.begin(), sa.end(), 0);
    sort(sa.begin(), sa.end(), [&](int l, int r) {
        if (l == r) return false;
        while (l < n && r < n) {
            if (s[l] != s[r]) return s[l] < s[r];
            l++;
            r++;
        }
        return l == n;
    });
    return sa;
}

vector<int> sa_doubling(const vector<int> &s) {
    int n = int(s.size());
    vector<int> sa(n), rnk = s, tmp(n);
    iota(sa.begin(), sa.end(), 0);
    for (int k = 1; k < n; k *= 2) {
        auto cmp = [&](int x, int y) {
            if (rnk[x] != rnk[y]) return rnk[x] < rnk[y];
            int rx = x + k < n ? rnk[x + k] : -1;
            int ry = y + k < n ? rnk[y + k] : -1;
            return rx < ry;
        };
        sort(sa.begin(), sa.end(), cmp);
        tmp[sa[0]] = 0;
        for (int i = 1; i < n; i++) {
            tmp[sa[i]] = tmp[sa[i - 1]] + (cmp(sa[i - 1], sa[i]) ? 1 : 0);
        }
        swap(tmp, rnk);
    }
    return sa;
}

// SA-IS, linear-time suffix array construction
// Reference:
// G. Nong, S. Zhang, and W. H. Chan,
// Two Efficient Algorithms for Linear Time Suffix Array Construction
template <int THRESHOLD_NAIVE = 10, int THRESHOLD_DOUBLING = 40>
vector<int> sa_is(const vector<int> &s, int upper) {
    int n = int(s.size());
    if (n == 0) return {};
    if (n == 1) return {0};
    if (n == 2) {
        if (s[0] < s[1]) {
            return {0, 1};
        } else {
            return {1, 0};
        }
    }
    if (n < THRESHOLD_NAIVE) {
        return sa_naive(s);
    }
    if (n < THRESHOLD_DOUBLING) {
        return sa_doubling(s);
    }

    vector<int> sa(n);
    vector<bool> ls(n);
    for (int i = n - 2; i >= 0; i--) {
        ls[i] = (s[i] == s[i + 1]) ? ls[i + 1] : (s[i] < s[i + 1]);
    }
    vector<int> sum_l(upper + 1), sum_s(upper + 1);
    for (int i = 0; i < n; i++) {
        if (!ls[i]) {
            sum_s[s[i]]++;
        } else {
            sum_l[s[i] + 1]++;
        }
    }
    for (int i = 0; i <= upper; i++) {
        sum_s[i] += sum_l[i];
        if (i < upper) sum_l[i + 1] += sum_s[i];
    }

    auto induce = [&](const vector<int>& lms) {
        fill(sa.begin(), sa.end(), -1);
        vector<int> buf(upper + 1);
        copy(sum_s.begin(), sum_s.end(), buf.begin());
        for (auto d : lms) {
            if (d == n) continue;
            sa[buf[s[d]]++] = d;
        }
        copy(sum_l.begin(), sum_l.end(), buf.begin());
        sa[buf[s[n - 1]]++] = n - 1;
        for (int i = 0; i < n; i++) {
            int v = sa[i];
            if (v >= 1 && !ls[v - 1]) {
                sa[buf[s[v - 1]]++] = v - 1;
            }
        }
        copy(sum_l.begin(), sum_l.end(), buf.begin());
        for (int i = n - 1; i >= 0; i--) {
            int v = sa[i];
            if (v >= 1 && ls[v - 1]) {
                sa[--buf[s[v - 1] + 1]] = v - 1;
            }
        }
    };

    vector<int> lms_map(n + 1, -1);
    int m = 0;
    for (int i = 1; i < n; i++) {
        if (!ls[i - 1] && ls[i]) {
            lms_map[i] = m++;
        }
    }
    vector<int> lms;
    lms.reserve(m);
    for (int i = 1; i < n; i++) {
        if (!ls[i - 1] && ls[i]) {
            lms.push_back(i);
        }
    }

    induce(lms);

    if (m) {
        vector<int> sorted_lms;
        sorted_lms.reserve(m);
        for (int v : sa) {
            if (lms_map[v] != -1) sorted_lms.push_back(v);
        }
        vector<int> rec_s(m);
        int rec_upper = 0;
        rec_s[lms_map[sorted_lms[0]]] = 0;
        for (int i = 1; i < m; i++) {
            int l = sorted_lms[i - 1], r = sorted_lms[i];
            int end_l = (lms_map[l] + 1 < m) ? lms[lms_map[l] + 1] : n;
            int end_r = (lms_map[r] + 1 < m) ? lms[lms_map[r] + 1] : n;
            bool same = true;
            if (end_l - l != end_r - r) {
                same = false;
            } else {
                while (l < end_l) {
                    if (s[l] != s[r]) {
                        break;
                    }
                    l++;
                    r++;
                }
                if (l == n || s[l] != s[r]) same = false;
            }
            if (!same) rec_upper++;
            rec_s[lms_map[sorted_lms[i]]] = rec_upper;
        }

        auto rec_sa =
            sa_is<THRESHOLD_NAIVE, THRESHOLD_DOUBLING>(rec_s, rec_upper);

        for (int i = 0; i < m; i++) {
            sorted_lms[i] = lms[rec_sa[i]];
        }
        induce(sorted_lms);
    }
    return sa;
}

}  // namespace internal

vector<int> suffix_array(const vector<int> &s, int upper) {
    assert(0 <= upper);
    for (int d : s) {
        assert(0 <= d && d <= upper);
    }
    auto sa = internal::sa_is(s, upper);
    return sa;
}

template <class T> vector<int> suffix_array(const vector<T> &s) {
    int n = int(s.size());
    vector<int> idx(n);
    iota(idx.begin(), idx.end(), 0);
    sort(idx.begin(), idx.end(), [&](int l, int r) { return s[l] < s[r]; });
    vector<int> s2(n);
    int now = 0;
    for (int i = 0; i < n; i++) {
        if (i && s[idx[i - 1]] != s[idx[i]]) now++;
        s2[idx[i]] = now;
    }
    return internal::sa_is(s2, now);
}

vector<int> suffix_array(const string &s) {
    int n = int(s.size());
    vector<int> s2(n);
    for (int i = 0; i < n; i++) {
        s2[i] = s[i];
    }
    return internal::sa_is(s2, 255);
}

// Reference:
// T. Kasai, G. Lee, H. Arimura, S. Arikawa, and K. Park,
// Linear-Time Longest-Common-Prefix Computation in Suffix Arrays and Its
// Applications
template <class T>
vector<int> lcp_array(const vector<T> &s,
                           const vector<int> &sa) {
    int n = int(s.size());
    assert(n >= 1);
    vector<int> rnk(n);
    for (int i = 0; i < n; i++) {
        rnk[sa[i]] = i;
    }
    vector<int> lcp(n - 1);
    int h = 0;
    for (int i = 0; i < n; i++) {
        if (h > 0) h--;
        if (rnk[i] == 0) continue;
        int j = sa[rnk[i] - 1];
        for (; j + h < n && i + h < n; h++) {
            if (s[j + h] != s[i + h]) break;
        }
        lcp[rnk[i] - 1] = h;
    }
    return lcp;
}

vector<int> lcp_array(const string &s, const vector<int> &sa) {
    int n = int(s.size());
    vector<int> s2(n);
    for (int i = 0; i < n; i++) {
        s2[i] = s[i];
    }
    return lcp_array(s2, sa);
}

// Reference:
// D. Gusfield,
// Algorithms on Strings, Trees, and Sequences: Computer Science and
// Computational Biology
template <class T> vector<int> z_algorithm(const vector<T> &s) {
    int n = int(s.size());
    if (n == 0) return {};
    vector<int> z(n);
    z[0] = 0;
    for (int i = 1, j = 0; i < n; i++) {
        int& k = z[i];
        k = (j + z[j] <= i) ? 0 : min(j + z[j] - i, z[i - j]);
        while (i + k < n && s[k] == s[i + k]) k++;
        if (j + z[j] < i + z[i]) j = i;
    }
    z[0] = n;
    return z;
}

vector<int> z_algorithm(const string &s) {
    int n = int(s.size());
    vector<int> s2(n);
    for (int i = 0; i < n; i++) {
        s2[i] = s[i];
    }
    return z_algorithm(s2);
}

int op1(int x, int y) { return min({x, y}); }
int e1() { return INF; }

int op2(int x, int y) { return max({x, y}); }
int e2() { return -INF; }

signed main() {
    string S;
    cin >> S;
    int N = S.size();

    vector<int> SA = suffix_array(S);

    segtree<int, op1, e1> seg1(SA); // 区間最少
    segtree<int, op2, e2> seg2(SA); // 区間最大

    int Q;
    cin >> Q;
    for (int q = 0; q < Q; q++) {
        string x, y;
        cin >> x >> y;
        int X = x.size();
        int Y = y.size();

        int ok = N - 1;
        int ng = -1;

        while (abs(ng - ok) > 1) {
            int mid = ceil(ng + ok, 2);

            if (S.substr(SA[mid], X) < x) ng = mid;
            else ok = mid;
        }

        if (S.substr(SA[ok], X) != x) { // 1つも含まれない
            cout << 0 << endl;
            continue;
        }

        int lx = ok;

        ok = 0;
        ng = N;

        while (abs(ng - ok) > 1) {
            int mid = ceil(ng + ok, 2);

            if (S.substr(SA[mid], X) > x) ng = mid;
            else ok = mid;
        }

        int rx = ok;

        ok = N - 1;
        ng = -1;

        while (abs(ng - ok) > 1) {
            int mid = ceil(ng + ok, 2);

            if (S.substr(SA[mid], Y) < y) ng = mid;
            else ok = mid;
        }

        if (S.substr(SA[ok], Y) != y) { // 1つも含まれない
            cout << 0 << endl;
            continue;
        }

        int ly = ok;

        ok = 0;
        ng = N;

        while (abs(ng - ok) > 1) {
            int mid = ceil(ng + ok, 2);

            if (S.substr(SA[mid], Y) > y) ng = mid;
            else ok = mid;
        }

        int ry = ok;

        if (seg2.prod(ly, ry + 1) + Y < seg1.prod(lx, rx + 1) + X) cout << 0 << endl;
        else if (seg1.prod(lx, rx + 1) > seg2.prod(ly, ry + 1)) cout << 0 << endl;
        else cout << seg2.prod(ly, ry + 1) + Y - seg1.prod(lx, rx + 1) << endl;
    }
}
accuracy: 1
time_ms: 60
memory_kb: 9232
final_rank: 1

code_snippet: #line 2 "cp-library/src/cp-template.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull  = unsigned long long;
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
template < class T > bool chmin(T& a, T b) { if(a > b) { a = b; return true; } return false; }
template < class T > bool chmax(T& a, T b) { if(a < b) { a = b; return true; } return false; }
template < class T, class U > T ceil (T x, U y) { return (x > 0 ? (x + y - 1) / y :           x / y); }
template < class T, class U > T floor(T x, U y) { return (x > 0 ?           x / y : (x - y + 1) / y); }
int popcnt(i32 x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(i64 x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }

#line 2 "cp-library/src/utility/rep_itr.hpp"
template < class T > struct itr_rep {
    T i, d;
    constexpr itr_rep(const T i) noexcept : i(i), d(1) {}
    constexpr itr_rep(const T i, const T d) noexcept : i(i), d(d) {}
    void operator++() noexcept { i += d; }
    constexpr int operator*() const noexcept { return i; }
    constexpr bool operator!=(const itr_rep x) const noexcept { return d > 0 ? i < x.i : i > x.i; }
};

template < class T > struct rep {
    const itr_rep< T > s, t;
    constexpr rep(const T t) noexcept : s(0), t(t) {}
    constexpr rep(const T s, const T t) noexcept : s(s), t(t) {}
    constexpr rep(const T s, const T t, const T d) noexcept : s(s, d), t(t, d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};

template < class T > struct revrep {
    const itr_rep < T > s, t;
    constexpr revrep(const T t) noexcept : s(t - 1, -1), t(-1, -1) {}
    constexpr revrep(const T s, const T t) noexcept : s(t - 1, -1), t(s - 1, -1) {}
    constexpr revrep(const T s, const T t, const T d) noexcept : s(t - 1, -d), t(s - 1, -d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};
#line 3 "cp-library/src/utility/io.hpp"

/* 128bit integer */
istream& operator>>(istream& is, i128& x) {
    std::string s; is >> s;
    int pm = (s[0] == '-');
    x = 0;
    for(int i : rep(pm, int(s.size()))) x = x * 10 + (s[i] - '0');
    if(pm) x *= -1;
    return is;
}
ostream& operator<<(ostream& os, const i128& x) {
    if(x == 0) return os << '0';
    i128 y = x;
    if(y < 0) { os << '-'; y *= -1; }
    std::vector<int> ny;
    while(y > 0) { ny.push_back(y % 10); y /= 10; }
    for(int i : revrep(ny.size())) os << ny[i];
    return os;
}

template < class S, class T > istream& operator>>(istream& is,       std::pair< S, T >& x) { is >> x.first        >> x.second; return is; }
template < class S, class T > ostream& operator<<(ostream& os, const std::pair< S, T >& x) { os << x.first << " " << x.second; return os; }

namespace scanner {
    struct sca {
        template < class T > operator T() {
            T s; std::cin >> s; return s;
        }
    };
    struct vec {
        int n;
        vec(int n) : n(n) {}
        template < class T > operator std::vector< T >() {
            std::vector< T > v(n);
            for(T& x : v) std::cin >> x;
            return v;
        }
    };
    struct mat {
        int h, w;
        mat(int h, int w) : h(h), w(w) {}
        template < class T > operator std::vector< std::vector< T > >() {
            std::vector m(h, std::vector< T >(w));
            for(std::vector< T >& v : m) for(T& x : v) std::cin >> x;
            return m;
        }
    };
    struct speedup {
        speedup() {
            std::cin.tie(0);
            std::ios::sync_with_stdio(0);
        }
    } speedup_instance;
}
scanner::sca in() { return scanner::sca(); }
scanner::vec in(int n) { return scanner::vec(n); }
scanner::mat in(int h, int w) { return scanner::mat(h, w); }

namespace printer {
    void precision(int d) { std::cout << std::fixed << std::setprecision(d); }
    void flush() { std::cout.flush(); }
}

template < class T >
ostream& operator<<(ostream& os, const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) { os << a[i]; if(i != n - 1) os << ' '; }
    return os;
}

int print() { std::cout << '\n'; return 0; }
template < class head, class... tail > int print(head&& h, tail&&... t) {
    std::cout << h; if(sizeof...(tail)) std::cout << ' ';
    return print(std::forward<tail>(t)...);
}
template < class T > int print_n(const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) std::cout << a[i] << "\n";
    return 0;
}


#line 2 "cp-library/src/utility/key_val.hpp"

template < class K, class V >
struct key_val {
    K key; V val;
    key_val() {}
    key_val(K key, V val) : key(key), val(val) {}
    template < std::size_t Index >
    std::tuple_element_t< Index, key_val >& get() {
        if constexpr (Index == 0) return key;
        if constexpr (Index == 1) return val;
    }
};

namespace std {

template < class K, class V > struct tuple_size < key_val< K, V > > : integral_constant< size_t, 2 > {};
template < class K, class V > struct tuple_element < 0, key_val< K, V > > { using type = K; };
template < class K, class V > struct tuple_element < 1, key_val< K, V > > { using type = V; };

}
#line 2 "cp-library/src/utility/vec_op.hpp"
template < class T > key_val< int, T > max_of(const vector< T >& a) {
    int i = std::max_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class T > key_val< int, T > min_of(const vector< T >& a) {
    int i = std::min_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class S, class T > S sum_of(const vector< T >& a) {
    S sum = 0;
    for(const T x : a) sum += x;
    return sum;
}
template < class S, class T > vector< S > freq_of(const vector< T >& a, T L, T R) {
    vector< S > res(R - L, S(0));
    for(const T x : a) res[x - L] += 1;
    return res;
}
template < class S, class T > struct prefix_sum {
    vector< S > s;
    prefix_sum(const vector< T >& a) : s(a) {
        s.insert(s.begin(), S(0));
        for(int i : rep(a.size())) s[i + 1] += s[i];
    }
    // [L, R)
    S sum(int L, int R) { return s[R] - s[L]; }
};
#line 3 "cp-library/src/utility/heap.hpp"

template < class T > using heap_min = std::priority_queue< T, std::vector< T >, std::greater< T > >;
template < class T > using heap_max = std::priority_queue< T, std::vector< T >, std::less< T > >;

#line 27 "cp-library/src/cp-template.hpp"

#line 1 "cp-library/src/algorithm/bin_search.hpp"
template < class T, class F >
T bin_search(T ok, T ng, F f) {
    while(abs(ng - ok) > 1) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

template < class T, class F >
T bin_search_real(T ok, T ng, F f, int step = 80) {
    while(step--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
#line 2 "cp-library/src/algorithm/argsort.hpp"

template < class T > std::vector< int > argsort(const std::vector< T > &a) {
    std::vector< int > ids((int)a.size());
    std::iota(ids.begin(), ids.end(), 0);
    std::sort(ids.begin(), ids.end(), [&](int i, int j) {
        return a[i] < a[j] || (a[i] == a[j] && i < j);
    });
    return ids;
}
#line 1 "macro.hpp"
namespace macro {

using size_type = int;
template < class container > void  sort(container& a) { std::sort(std:: begin(a), std:: end(a)); }
template < class container > void rsort(container& a) { std::sort(std::rbegin(a), std::rend(a)); }
template < class container > void reverse(container& a) { std::reverse(std::begin(a), std::end(a)); }
template < class container > void unique(container& a) {
    std::sort(std::begin(a), std::end(a));
    a.erase(std::unique(std::begin(a), std::end(a)), std::end(a));
}
template < class container > container  sorted(const container& a) { container b = a;  sort(b); return std::move(b); }
template < class container > container rsorted(const container& a) { container b = a; rsort(b); return std::move(b); }
template < class container, class compare > void sort(container& a, const compare& cmp) { std::sort(std::begin(a), std::end(a), cmp); }
template < class container, class compare > container sorted(const container& a, const compare& cmp) { container b = a; sort(b, cmp); return std::move(b); }
template < class container, class value > size_type lower_bound(const container& a, const value& x) { return std::lower_bound(std::begin(a), std::end(a), x) - std::begin(a); }
template < class container, class value > size_type upper_bound(const container& a, const value& x) { return std::upper_bound(std::begin(a), std::end(a), x) - std::begin(a); }

const std::vector<std::pair<size_type, size_type>> dir4 = { {+1,  0}, {-1,  0}, { 0, +1}, { 0, -1} };
const std::vector<std::pair<size_type, size_type>> dir8 = { {-1, -1}, {-1,  0}, {-1, +1}, { 0, -1}, { 0, +1}, {+1, -1}, {+1,  0}, {+1, +1} };

#ifdef _DEBUG
#define debug(x) std::cout << "[" << __LINE__ << "] " << #x << ": " << x << std::endl
#else
#define debug(x)
#endif

template < class container > void concat(container& a, const container& b) {
    a.insert(std::end(a), std::begin(b), std::end(b));
}
std::vector<size_type> iota(const size_type n) {
    std::vector<size_type> I(n);
    std::iota(std::begin(I), std::end(I), 0);
    return I;
}
template < class container > std::vector<size_type> sort_idx(const container& a) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return a[i] < a[j] or (a[i] == a[j] and i < j); });
    return I;
}
template < class container, class compare > std::vector<size_type> sort_idx(const container& a, const compare& cmp) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return cmp(a[i], a[j]) or (a[i] == a[j] and i < j); });
    return std::move(I);
}

struct grid {
    using size_type = int;
    size_type H, W;
    grid(const size_type H, const size_type W) : H(H), W(W) {}
    bool contains(const size_type i, const size_type j) {
        return 0 <= i and i < H and 0 <= j and j < W;
    }
};

} // namespace macro

using namespace macro;
#line 1 "cp-library/src/data_structure/segtree.hpp"
template < class monoid > struct segtree {
    using S = typename monoid::set;

    segtree() : segtree(0) {}
    segtree(int n) : segtree(vector< S >(n, monoid::id())) {}
    segtree(int n, S s) : segtree(vector< S >(n, s)) {}
    segtree(const vector< S >& v) : _n(int(v.size())) {
        log = ceil_pow2(_n);
        size = 1 << log;
        d = vector< S >(2 * size, monoid::id());
        for(int i = 0; i < _n; i++) d[size + i] = v[i];
        for(int i = size - 1; i >= 1; i--) update(i);
    }
    // a[i] <- x
    void set(int i, S x) {
        assert(0 <= i && i < _n);
        i += size;
        d[i] = x;
        for(int p = 1; p <= log; p++) update(i >> p);
    }
    // a[i]
    S get(int i) {
        assert(0 <= i && i < _n);
        return d[i + size];
    }
    // [l, r)
    S prod(int l, int r) {
        assert(0 <= l && l <= r && r <= _n);
        S sml = monoid::id(), smr = monoid::id();
        l += size, r += size;
        while(l < r) {
            if(l & 1) sml = monoid::op(sml, d[l++]);
            if(r & 1) smr = monoid::op(d[--r], smr);
            l >>= 1, r >>= 1;
        }
        return monoid::op(sml, smr);
    }
    S all_prod() { return d[1]; }
    template < class func > int max_right(int l, func f) {
        assert(0 <= l && l <= _n);
        assert(f(monoid::id()));
        if(l == _n) return _n;
        l += size;
        S sm = monoid::id();
        do {
            while(l % 2 == 0) l >>= 1;
            if(!f(monoid::op(sm, d[l]))) {
                while(l < size) {
                    l = 2 * l;
                    if(f(monoid::op(sm, d[l]))) {
                        sm = monoid::op(sm, d[l]);
                        l++;
                    }
                }
                return l - size;
            }
            sm = monoid::op(sm, d[l]);
            l++;
        } while((l & -l) != l);
        return _n;
    }
    template < class func > int min_left(int r, func f) {
        assert(0 <= r && r <= _n);
        assert(f(monoid::id()));
        if(r == 0) return 0;
        r += size;
        S sm = monoid::id();
        do {
            r--;
            while(r > 1 && (r % 2)) r >>= 1;
            if(!f(monoid::op(d[r], sm))) {
                while(r < size) {
                    r = 2 * r + 1;
                    if(f(monoid::op(d[r], sm))) {
                        sm = monoid::op(d[r], sm);
                        r--;
                    }
                }
                return r + 1 - size;
            }
            sm = monoid::op(d[r], sm);
        } while((r & -r) != r);
        return 0;
    }

  private:
    int _n, size, log;
    vector< S > d;
    int ceil_pow2(int n) { int x = 0; while((1U << x) < uint(n)) x++; return x; }
    void update(int k) { d[k] = monoid::op(d[2 * k], d[2 * k + 1]); }
};
#line 3 "cp-library/src/algebra/minmax.hpp"

template < class T > class min_monoid {
  public:
    using set = T;
    static constexpr T op(const T &l, const T &r) { return std::min(l, r); }
    static constexpr T id() { return std::numeric_limits< T >::max(); }
    static constexpr bool comm = true;
};

template < class T > class max_monoid {
  public:
    using set = T;
    static constexpr T op(const T &l, const T &r) { return std::max(l, r); }
    static constexpr T id() { return std::numeric_limits< T >::min(); }
    static constexpr bool comm = true;
};
#line 5 "A.cpp"

struct suffix_array {
    int n;
    string s;
    vector<int> sa, rank, tmp;
    segtree<min_monoid<int>> rmq;
    suffix_array(const string& s) : s(s), n(s.size()), sa(n + 1), rank(n + 1), tmp(n + 1) {
        for(int i = 0; i <= n; i++) {
            sa[i] = i;
            rank[i] = i < n ? s[i] : -1;
        }

        for(int k = 1; k <= n; k *= 2) {
            auto cmp = [&](int i, int j) {
                if(rank[i] != rank[j]) return rank[i] < rank[j];
                int ri = i + k <= n ? rank[i + k] : -1;
                int rj = j + k <= n ? rank[j + k] : -1;
                return ri < rj; 
            };
            sort(sa, cmp);
            tmp[sa[0]] = 0;
            for(int i = 1; i <= n; i++) 
                tmp[sa[i]] = tmp[sa[i - 1]] + cmp(sa[i - 1], sa[i]);
            for(int i = 0; i <= n; i++) rank[i] = tmp[i];
        }

        rmq = segtree<min_monoid<int>>(sa);
    }

    int first(const string& t) {
        int L = 0, R = n;
        while(R - L > 1) {
            int M = (L + R) / 2;
            (s.compare(sa[M], t.size(), t) < 0 ? L : R) = M;
        }
        if(s.compare(sa[R], t.size(), t) == 0) {
            return R;
        } else {
            return -1;
        }
    }

    int last(const string& t) {
        int L = 1, R = n + 1;
        while(R - L > 1) {
            int M = (L + R) / 2;
            (s.compare(sa[M], t.size(), t) <= 0 ? L : R) = M;
        }
        if(s.compare(sa[L], t.size(), t) == 0) {
            return L;
        } else {
            return -1;
        }
    }

    int leftest(const string& t) {
        int L = first(t);
        if(L == -1) return -1;
        int R = last(t);
        return rmq.prod(L, R + 1);
    }
};

int main() {
    string s = in();
    string rev_s = s; reverse(rev_s);
    suffix_array sa(s), rev_sa(rev_s);
    const int n = s.size();

    int m = in();
    for(int m_ : rep(m)) {
        string x = in(), y = in();
        reverse(y);
        int xi = sa.leftest(x);
        int yi = rev_sa.leftest(y);
        if(xi == -1 or yi == -1) {
            print(0);
        } else {
            yi = n - 1 - yi;
            if(xi + x.size() - 1 <= yi and xi <= yi - y.size() + 1) {
                print(yi - xi + 1);
            } else {
                print(0);
            }
        }
    }
}
accuracy: 1
time_ms: 310
memory_kb: 13152
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define rep(i, n) for (int i = 0; i < (n); i++)
#define per(i, n) for (int i = (n)-1; i >= 0; i--)
#define rep2(i, l, r) for (int i = (l); i < (r); i++)
#define per2(i, l, r) for (int i = (r)-1; i >= (l); i--)
#define each(e, x) for (auto &e : x)
#define sz(x) (int)x.size()
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)
#define eb emplace_back
#define MM << ' ' <<
#define TT template <typename T>
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;

TT bool chmin(T &x, T y) { return x > y ? (x = y, true) : false; }
TT bool chmax(T &x, T y) { return x > y ? (x = y, true) : false; }

TT using minheap = priority_queue<T, vector<T>, greater<T>>;
TT using maxheap = priority_queue<T>;

TT void print(vector<T> v, T x = 0) {
    int n = sz(v);
    rep(i, n) cout << v[i] + x << (i == n - 1 ? '\n' : ' ');
    if (n == 0) cout << '\n';
}

TT void printn(vector<T> v, T x = 0) {
    int n = sz(v);
    rep(i, n) cout << v[i] + x << '\n';
}

TT void rearrange(vector<T> &v) {
    sort(all(v));
    v.erase(unique(all(v)), end(v));
}

TT int lb(vector<T> &v, T x) { return lower_bound(all(v), x) - begin(v); }
TT int ub(vector<T> &v, T x) { return upper_bound(all(v), x) - begin(v); }

struct io_setup {
    io_setup() {
        ios_base::sync_with_stdio(false);
        cin.tie(NULL);
        cout << fixed << setprecision(15);
    }
} io_setup;

vector<int> suffix_array(string S) {
    int n = sz(S);
    vector<int> sa(n);
    iota(all(sa), 0);
    sort(all(sa), [&](int i, int j) { return S[i] == S[j] ? i > j : S[i] < S[j]; });
    vector<int> rank(n), c(n), cnt(n);
    rep(i, n) c[i] = S[i];
    for (int len = 1; len < n; len <<= 1) {
        rep(i, n) {
            if (i == 0 || c[sa[i - 1]] != c[sa[i]]) {
                rank[sa[i]] = i;
            } else {
                if (sa[i - 1] + len >= n || c[sa[i - 1] + len / 2] != c[sa[i] + len / 2]) {
                    rank[sa[i]] = i;
                } else {
                    rank[sa[i]] = rank[sa[i - 1]];
                }
            }
        }
        iota(all(cnt), 0);
        copy(all(sa), begin(c));
        rep(i, n) {
            int j = c[i] - len;
            if (j >= 0) sa[cnt[rank[j]]++] = j;
        }
        swap(rank, c);
    }
    return sa;
}

vector<int> lcp_array(string S, vector<int> sa) {
    int n = sz(S);
    vector<int> rank(n), lcp(n - 1);
    rep(i, n) rank[sa[i]] = i;
    int h = 0;
    rep(i, n) {
        if (rank[i] + 1 < n) {
            int j = sa[rank[i] + 1];
            while (max(i, j) + h < n && S[i + h] == S[j + h]) h++;
            lcp[rank[i]] = h;
            if (h > 0) h--;
        }
    }
    return lcp;
}

struct Segment_Tree {
    vector<int> data;
    int n;
    const int e = INT_MAX;

    int f(int a, int b) { return min(a, b); }

    Segment_Tree(vector<int> v) {
        int m = sz(v);
        n = 1;
        while (n < m) n <<= 1;
        data.assign(2 * n, e);
        rep(i, m) data[n + i] = v[i];
        per2(i, 1, n) data[i] = f(data[2 * i], data[2 * i + 1]);
    }

    int query(int l, int r, int k = 1, int L = 0, int R = -1) {
        if (R == -1) R = n;
        if (r <= L || R <= l) return e;
        if (l <= L && R <= r) {
            // cout << l MM r MM k MM L MM R << '\n';
            return data[k];
        }
        int M = (L + R) / 2;
        return f(query(l, r, 2 * k, L, M), query(l, r, 2 * k + 1, M, R));
    }
};

int main() {
    string S;
    cin >> S;

    int N = sz(S);

    int Q;
    cin >> Q;

    vector<string> X(Q), Y(Q);
    rep(i, Q) cin >> X[i] >> Y[i], reverse(all(Y[i]));

    string A = S, B = S;
    reverse(all(B));
    rep(i, Q) A += X[i], B += Y[i];

    // cout << A << '\n' << B << '\n';

    vector<int> sa = suffix_array(A), sb = suffix_array(B);
    vector<int> la = lcp_array(A, sa), lb = lcp_array(B, sb);

    vector<int> ra(sz(sa)), rb(sz(sb));
    rep(i, sz(sa)) ra[sa[i]] = i;
    rep(i, sz(sb)) rb[sb[i]] = i;

    // print(sa), print(sb), print(la), print(lb);

    vector<int> L(Q, N), R(Q, -1);
    int a = N, b = N;

    Segment_Tree segsa(sa), segsb(sb), segla(la), seglb(lb);

    rep(i, Q) {
        {
            int p = ra[a];
            int l, r;
            {
                int ok = p, ng = -1;
                while (ok - ng > 1) {
                    int mid = (ok + ng) / 2;
                    (segla.query(mid, p) >= sz(X[i]) ? ok : ng) = mid;
                }
                l = ok;
            }
            {
                int ok = p, ng = sz(sa);
                while (ng - ok > 1) {
                    int mid = (ok + ng) / 2;
                    (segla.query(p, mid) >= sz(X[i]) ? ok : ng) = mid;
                }
                r = ok;
            }
            // cout << l MM p MM r << '\n';
            L[i] = segsa.query(l, r + 1);
            a += sz(X[i]);
        }
        {
            int p = rb[b];
            int l, r;
            {
                int ok = p, ng = -1;
                while (ok - ng > 1) {
                    int mid = (ok + ng) / 2;
                    (seglb.query(mid, p) >= sz(Y[i]) ? ok : ng) = mid;
                }
                l = ok;
            }
            {
                int ok = p, ng = sz(sb);
                while (ng - ok > 1) {
                    int mid = (ok + ng) / 2;
                    (seglb.query(p, mid) >= sz(Y[i]) ? ok : ng) = mid;
                }
                r = ok;
            }
            // cout << Y[i] MM l MM p MM r << endl;
            // print(vector<int>(begin(sb) + l, begin(sb) + r + 1));
            R[i] = N - segsb.query(l, r + 1);
            b += sz(Y[i]);
        }
    }

    rep(i, Q) {
        // cout << L[i] MM R[i] << '\n';
        if (L[i] + sz(X[i]) > R[i] || L[i] > R[i] - sz(Y[i])) {
            cout << 0 << '\n';
        } else {
            cout << R[i] - L[i] << '\n';
        }
    }
}
accuracy: 1
time_ms: 1160
memory_kb: 35628
final_rank: 15

code_snippet: //
// Suffix Array (SA-IS) (O(N))
//   G. Nong, S. Zhang, and W. H. Chan:
//   Two Efficient Algorithms for Linear Time Suffix Array Construction
//
// verified
//   Yosupo Judge Suffix Array
//     https://judge.yosupo.jp/problem/suffixarray
//
//   ARC 060 F - 最良表現 (verify get_lcp() using sparse table)
//     https://beta.atcoder.jp/contests/arc060/tasks/arc060_d
//
//   AOJ 2644 Longest Match (verify lower_bound())
//     https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2644
//


#include <bits/stdc++.h>
using namespace std;


// Sparse Table
template<class MeetSemiLattice> struct SparseTable {
    vector<vector<MeetSemiLattice> > dat;
    vector<int> height;
    
    SparseTable() { }
    SparseTable(const vector<MeetSemiLattice> &vec) { init(vec); }
    void init(const vector<MeetSemiLattice> &vec) {
        int n = (int)vec.size(), h = 1;
        while ((1<<h) < n) ++h;
        dat.assign(h, vector<MeetSemiLattice>(1<<h));
        height.assign(n+1, 0);
        for (int i = 2; i <= n; i++) height[i] = height[i>>1]+1;
        for (int i = 0; i < n; ++i) dat[0][i] = vec[i];
        for (int i = 1; i < h; ++i)
            for (int j = 0; j < n; ++j)
                dat[i][j] = min(dat[i-1][j], dat[i-1][min(j+(1<<(i-1)),n-1)]);
    }
    
    MeetSemiLattice get(int a, int b) {
        return min(dat[height[b-a]][a], dat[height[b-a]][b-(1<<height[b-a])]);
    }
};

// SA-IS (O(N))
template<class Str> struct SuffixArray {
    // data
    Str str;
    vector<int> sa;    // sa[i] : the starting index of the i-th smallest suffix (i = 0, 1, ..., n)
    vector<int> rank;  // rank[sa[i]] = i
    vector<int> lcp;   // lcp[i]: the lcp of sa[i] and sa[i+1] (i = 0, 1, ..., n-1)
    SparseTable<int> st;  // use for calcultating lcp(i, j)

    // getter
    int& operator [] (int i) {
        return sa[i];
    }
    vector<int> get_sa() { return sa; }
    vector<int> get_rank() { return rank; }
    vector<int> get_lcp() { return lcp; }

    // constructor
    SuffixArray() {}
    SuffixArray(const Str& str_, bool no_limit_elements = false) : str(str_) {
        build_sa(no_limit_elements);
    }
    void init(const Str& str_, bool no_limit_elements = false) {
        str = str_;
        build_sa(no_limit_elements);
    }
    void build_sa(bool no_limit_elements = false) {
        vector<int> s;
        int num_of_chars = 256;
        if (!no_limit_elements) {
            for (int i = 0; i < (int)str.size(); ++i) {
                s.push_back(str[i] + 1);
            }
        } else {
            unordered_map<int,int> dict;
            for (int i = 0; i < (int)str.size(); ++i) {
                if (!dict.count(str[i])) dict[str[i]] = dict.size();
            }
            for (int i = 0; i < (int)str.size(); ++i) {
                s.push_back(dict[str[i]] + 1);
            }
            num_of_chars = (int)dict.size();
        }
        s.push_back(0);
        sa = sa_is(s, num_of_chars);
        build_lcp(s);
        build_sparse_table();
    }

    // SA-IS
    // upper: # of characters
    vector<int> sa_is(vector<int> &s, int num_of_chars = 256) {
        int N = (int)s.size();
        if (N == 0) return {};
        else if (N == 1) return {0};
        else if (N == 2) {
            if (s[0] < s[1]) return {0, 1};
            else return {1, 0};
        }

        vector<int> isa(N);
        vector<bool> ls(N, false);
        for (int i = N - 2; i >= 0; --i) {
            ls[i] = (s[i] == s[i + 1]) ? ls[i + 1] : (s[i] < s[i + 1]);
        }
        vector<int> sum_l(num_of_chars + 1, 0), sum_s(num_of_chars + 1, 0);
        for (int i = 0; i < N; ++i) {
            if (!ls[i]) ++sum_s[s[i]];
            else ++sum_l[s[i] + 1];
        }
        for (int i = 0; i <= num_of_chars; ++i) {
            sum_s[i] += sum_l[i];
            if (i < num_of_chars) sum_l[i + 1] += sum_s[i];
        }

        auto induce = [&](const vector<int> &lms) -> void {
            fill(isa.begin(), isa.end(), -1);
            vector<int> buf(num_of_chars + 1);
            copy(sum_s.begin(), sum_s.end(), buf.begin());
            for (auto d: lms) {
                if (d == N) continue;
                isa[buf[s[d]]++] = d;
            }
            copy(sum_l.begin(), sum_l.end(), buf.begin());
            isa[buf[s[N - 1]]++] = N - 1;
            for (int i = 0; i < N; ++i) {
                int v = isa[i];
                if (v >= 1 && !ls[v - 1]) {
                    isa[buf[s[v - 1]]++] = v - 1;
                }
            }
            copy(sum_l.begin(), sum_l.end(), buf.begin());
            for (int i = N - 1; i >= 0; --i) {
                int v = isa[i];
                if (v >= 1 && ls[v - 1]) {
                    isa[--buf[s[v - 1] + 1]] = v - 1;
                }
            }
        };
            
        vector<int> lms, lms_map(N + 1, -1);
        int M = 0;
        for (int i = 1; i < N; ++i) {
            if (!ls[i - 1] && ls[i]) {
                lms_map[i] = M++;
            }
        }
        lms.reserve(M);
        for (int i = 1; i < N; ++i) {
            if (!ls[i - 1] && ls[i]) {
                lms.push_back(i);
            }
        }
        induce(lms);

        if (M) {
            vector<int> lms2;
            lms2.reserve(isa.size());
            for (auto v: isa) {
                if (lms_map[v] != -1) lms2.push_back(v);
            }
            int rec_upper = 0;
            vector<int> rec_s(M);
            rec_s[lms_map[lms2[0]]] = 0;
            for (int i = 1; i < M; ++i) {
                int l = lms2[i - 1], r = lms2[i];
                int nl = (lms_map[l] + 1 < M) ? lms[lms_map[l] + 1] : N;
                int nr = (lms_map[r] + 1 < M) ? lms[lms_map[r] + 1] : N;
                bool same = true;
                if (nl - l != nr - r) same = false;
                else {
                    while (l < nl) {
                        if (s[l] != s[r]) break;
                        ++l, ++r;
                    }
                    if (l == N || s[l] != s[r]) same = false;
                }
                if (!same) ++rec_upper;
                rec_s[lms_map[lms2[i]]] = rec_upper;
            }
            auto rec_sa = sa_is(rec_s, rec_upper);

            vector<int> sorted_lms(M);
            for (int i = 0; i < M; ++i) {
                sorted_lms[i] = lms[rec_sa[i]];
            }
            induce(sorted_lms);
        }
        return isa;
    }

    // find min id that str.substr(sa[id]) >= T
    int lower_bound(const Str& T) {
        int left = -1, right = sa.size();
        while (right - left > 1) {
            int mid = (left + right) / 2;
            if (str.compare(sa[mid], string::npos, T) < 0)
                left = mid;
            else
                right = mid;
        }
        return right;
    }

    // find min id that str.substr(sa[id], T.size()) > T
    int upper_bound(const Str& T) {
        int left = -1, right = sa.size();
        while (right - left > 1) {
            int mid = (left + right) / 2;
            if (str.compare(sa[mid], T.size(), T) <= 0)
                left = mid;
            else
                right = mid;
        }
        return right;
    }

    // search
    bool is_contain(const Str& T) {
        int lb = lower_bound(T);
        if (lb >= sa.size()) return false;
        return str.compare(sa[lb], T.size(), T) == 0;
    }

    // find lcp
    void build_lcp(const vector<int> &s) {
        int N = (int)s.size();
        rank.assign(N, 0), lcp.assign(N - 1, 0);
        for (int i = 0; i < N; ++i) rank[sa[i]] = i;
        int h = 0;
        for (int i = 0; i < N - 1; ++i) {
            int pi = sa[rank[i] - 1];
            if (h > 0) --h;
            for (; pi + h < N && i + h < N; ++h) {
                if (s[pi + h] != s[i + h]) break;
            }
            lcp[rank[i] - 1] = h;
        }
    }
    
    // build sparse table for calculating lcp
    void build_sparse_table() {
        st.init(lcp);
    }

    // calc lcp of str.sutstr(a) and str.substr(b)
    int get_lcp(int a, int b) {
        return st.get(min(rank[a], rank[b]), max(rank[a], rank[b]));
    }

    // debug
    void dump() {
        for (int i = 0; i < sa.size(); ++i) {
            cout << i << ": " << sa[i] << ", " << str.substr(sa[i]) << endl;
        }
    }
};



/*/////////////////////////////*/
// Examples
/*/////////////////////////////*/

// Yosupo Judge Suffix Array
void YosupoJudgeSuffixArray() {
    string S;
    cin >> S;
    SuffixArray sa(S);
    for (int i = 0; i < S.size(); ++i) {
        cout << sa[i + 1] << " ";
    }
    cout << endl;
}

// ARC 060 F - 最良表現
void ARC_060_F() {
    string str;
    cin >> str;
    int n = (int)str.size();

    // n の約数を求める
    vector<long long> divs;
    for (long long i = 1LL; i*i <= n; ++i) {
        if (n%i == 0LL) {
            divs.push_back(i);
            long long temp = n/i;
            if (i != temp) divs.push_back(temp);
        }
    }
    sort(divs.begin(), divs.end());

    // 求める
    long long syuuki = n;
    for (auto d : divs) {
        bool ok = true;
        for (int j = 0; j + d < n; ++j) {
            if (str[j] != str[j+d]) ok = false;
        }
        if (ok) syuuki = min(syuuki, d);
    }
    if (syuuki == n) cout << 1 << endl << 1 << endl;
    else if (syuuki == 1) cout << n << endl << 1 << endl;
    else {
        vector<int> cannot_cut(n*2, 0);
        SuffixArray sa(str);
        for (int d = 1; d < n; ++d) {
            for (int dd = d; dd < n; dd += d) {
                int lcp = sa.get_lcp(0, dd);
                if (lcp < d) break;
                cannot_cut[dd + d] = true;
            }
            for (int dd = n-d*2; dd >= 0; dd -= d) {
                int lcp = sa.get_lcp(dd, n-d);
                if (lcp < d) break;
                cannot_cut[dd] = true;
            }
        }
        int con = 0;
        for (int i = 1; i < n; ++i) if (!cannot_cut[i]) ++con;
        cout << 2 << endl << con << endl;
    }
}

// AOJ 2644
void AOJ_2644() {
    // Suffix Array の構築
    string S;
    cin >> S;
    SuffixArray<string> suf(S);
    vector<int> sa = suf.get_sa();

    // Suffix Array の区間に関する RMQ
    SparseTable<int> min_st(sa);
    for (auto& v : sa) v = -v;
    SparseTable<int> max_st(sa);

    auto solve = [&](const string& x, const string& y) -> int {
        if (!suf.is_contain(x) || !suf.is_contain(y)) {
            return 0;
        }
        int xl = suf.lower_bound(x);
        int xr = suf.upper_bound(x);
        int yl = suf.lower_bound(y);
        int yr = suf.upper_bound(y);
        int xres = min_st.get(xl, xr);
        int yres = -max_st.get(yl, yr);

        if (xres > yres || xres + x.size() > yres + y.size())
            return 0;
        else
            return yres - xres + (int)y.size();
    };

    // クエリ処理
    int Q;
    cin >> Q;
    while (Q--) {
        string x, y;
        cin >> x >> y;
        cout << solve(x, y) << endl;
    }
}


int main() {
    //YosupoJudgeSuffixArray();
    //ARC_060_F();
    AOJ_2644();
}
accuracy: 1
time_ms: 170
memory_kb: 65864
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define foa(s, v) for(auto &s : v)
#define all(v) v.begin(), v.end()
#define sz(v) int(v.size())

#define REPname(a, b, c, d, ...) d

#define rep(...) REPname(__VA_ARGS__, REP2, REP1, REP0)(__VA_ARGS__)
#define REP2(i, l, r) for(int i = int(l); i < int(r); ++i)
#define REP1(i, x) REP2(i, 0, x)
#define REP0(x) REP1(SPJ, x)

#define drep(...) REPname(__VA_ARGS__, DREP2, DREP1)(__VA_ARGS__)
#define DREP2(i, l, r) for(int i = int(r) - 1; i >= int(l); --i)
#define DREP1(i, x) DREP2(i, 0, x)

template <class T>
using V = vector<T>;
template <class T>
using pqmin = priority_queue<T, V<T>, greater<T>>;
using ll = long long;
using vi = V<int>;
constexpr ll INF = 1e18;
constexpr int inf = 1e9;

template <class T>
inline bool chmin(T &a, T b) {
	return a > b ? a = b, 1 : 0;
}

template <class T>
inline bool chmax(T &a, T b) {
	return a < b ? a = b, 1 : 0;
}

struct AC {
	enum {alpha = 26, first = 'a'};
	struct node {
		int back, next[alpha], start = -1, end = -1, nmatches = 0;
		node(int v) { memset (next, v, sizeof(next)); }
	};
	vector<node> N;
	vi backp;
	void insert(string& s, int j) {
		assert(!s.empty());
		int n = 0;
		for(char c : s) {
			int &m = N[n].next[c - first];
			if(m == -1) {n=m=sz(N); N.emplace_back(-1);}
			else n = m;
		}
		if(N[n].end == -1) N[n].start = j;
		backp.push_back(N[n].end);
		N[n].end = j;
		N[n].nmatches++;
	}
	AC(vector<string> &pat) : N(1, -1) {
		rep(i, sz(pat)) {
			insert(pat[i], i);
		}
		N[0].back = sz(N);
		N.emplace_back(0);
		queue<int> q;
		for(q.push(0) ; q.size(); q.pop()){
			int n = q.front(), prev = N[n].back;
			rep(i, alpha) {
				int &ed = N[n].next[i], y = N[prev].next[i];
				if(ed == -1) ed = y;
				else {
					N[ed].back = y;
					(N[ed].end == -1 ? N[ed].end : backp[N[ed].start]) = N[y].end;
					N[ed].nmatches += N[y].nmatches;
					q.push(ed);
				}
			}
			
		}
	}
	vi find(const string& word) {
		int n= 0;
		vi res;
		for(char c : word) {
			n = N[n].next[c - first];
			res.push_back(N[n].end);
		}
		return res;
	}
	vector<vi> findAll(vector<string>& pat, const string& word) {
		vi r = find(word);
		vector<vi> res(sz(word));
		rep(i, sz(word)) {
			int ind = r[i];
			while(ind != -1) 
			{
				res[i-sz(pat[ind]) + 1].push_back(ind);
				ind = backp[ind];
			}
		}
		return res;
	}
};

vector<int> first_match(string& base, vector<string> &words) {
	map<string, int> ids;
	foa(t, words) ids[t] = 0;
	int kinds = 0;
	vector<string> compressed;
	foa(t, ids) {
		t.second = kinds++;
		compressed.push_back(t.first);
	}
	vector<int> convert(sz(words));
	rep(i, sz(words)) convert[i] = ids[words[i]];

	AC ac(compressed);
	auto res = ac.findAll(compressed, base);
	vector<int> ret(sz(compressed), inf);
	rep(pos, sz(res)) {
		foa(idx, res[pos]) {
			chmin(ret[idx], pos);
		}
	}
	vector<int> ans(sz(words));
	rep(i, sz(ans)) {
		ans[i] = ret[convert[i]];
	}
	return ans;
}

string s;
void solve() {
	int m;
	cin >> m;
	string rev(s);
	reverse(all(rev));
	vector<string> x, y;
	rep(m) {
		string a, b;
		cin >> a >> b;
		x.push_back(a);
		reverse(all(b));
		y.push_back(b);
	}
	vi left = first_match(s, x);
	vi right = first_match(rev, y);
	rep(i, sz(left)) {
		int l = left[i];
		int r = right[i];
		int res = 0;
		if(l + r + max(sz(x[i]), sz(y[i])) > sz(s)) {
			res = 0;
		} else {
			res = sz(s) - l - r;
		}
		cout << res << '\n';
	}
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout << fixed << setprecision(15);
	srand((unsigned)time(NULL));
	while(cin >> s) solve();
}
accuracy: 1
time_ms: 20
memory_kb: 43968
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;

// Sparse Table
template<class MeetSemiLattice> struct SparseTable {
    vector<vector<MeetSemiLattice> > dat;
    vector<int> height;
    
    SparseTable() { }
    SparseTable(const vector<MeetSemiLattice> &vec) { init(vec); }
    void init(const vector<MeetSemiLattice> &vec) {
        int n = (int)vec.size(), h = 0;
        while ((1<<h) < n) ++h;
        dat.assign(h, vector<MeetSemiLattice>(1<<h));
        height.assign(n+1, 0);
        for (int i = 2; i <= n; i++) height[i] = height[i>>1]+1;
        for (int i = 0; i < n; ++i) dat[0][i] = vec[i];
        for (int i = 1; i < h; ++i)
            for (int j = 0; j < n; ++j)
                dat[i][j] = min(dat[i-1][j], dat[i-1][min(j+(1<<(i-1)),n-1)]);
    }
    
    MeetSemiLattice get(int a, int b) {
        return min(dat[height[b-a]][a], dat[height[b-a]][b-(1<<height[b-a])]);
    }
};

// SA-IS (O(N))
template<class Str> struct SuffixArray {
    // data
    Str str;
    vector<int> sa;    // sa[i] : the starting index of the i-th smallest suffix (i = 0, 1, ..., n)
    vector<int> rank;  // rank[sa[i]] = i
    vector<int> lcp;   // lcp[i]: the lcp of sa[i] and sa[i+1] (i = 0, 1, ..., n-1)
    SparseTable<int> st;  // use for calcultating lcp(i, j)

    // getter
    int& operator [] (int i) {
        return sa[i];
    }
    vector<int> get_sa() { return sa; }
    vector<int> get_rank() { return rank; }
    vector<int> get_lcp() { return lcp; }

    // constructor
    SuffixArray(const Str& str_) : str(str_) {
        build_sa();
    }
    void init(const Str& str_) {
        str = str_;
        build_sa();
    }
    void build_sa() {
        vector<int> s;
        for (int i = 0; i < (int)str.size(); ++i) {
            s.push_back(str[i] + 1);
        }
        s.push_back(0);
        sa = sa_is(s);
        calcLCP(s);
        buildSparseTable();
    }

    // SA-IS
    // upper: # of characters 
    vector<int> sa_is(vector<int> &s, int upper = 256) {
        int N = (int)s.size();
        if (N == 0) return {};
        else if (N == 1) return {0};
        else if (N == 2) {
            if (s[0] < s[1]) return {0, 1};
            else return {1, 0};
        }

        vector<int> isa(N);
        vector<bool> ls(N, false);
        for (int i = N - 2; i >= 0; --i) {
            ls[i] = (s[i] == s[i + 1]) ? ls[i + 1] : (s[i] < s[i + 1]);
        }
        vector<int> sum_l(upper + 1, 0), sum_s(upper + 1, 0);
        for (int i = 0; i < N; ++i) {
            if (!ls[i]) ++sum_s[s[i]];
            else ++sum_l[s[i] + 1];
        }
        for (int i = 0; i <= upper; ++i) {
            sum_s[i] += sum_l[i];
            if (i < upper) sum_l[i + 1] += sum_s[i];
        }

        auto induce = [&](const vector<int> &lms) -> void {
            fill(isa.begin(), isa.end(), -1);
            vector<int> buf(upper + 1);
            copy(sum_s.begin(), sum_s.end(), buf.begin());
            for (auto d: lms) {
                if (d == N) continue;
                isa[buf[s[d]]++] = d;
            }
            copy(sum_l.begin(), sum_l.end(), buf.begin());
            isa[buf[s[N - 1]]++] = N - 1;
            for (int i = 0; i < N; ++i) {
                int v = isa[i];
                if (v >= 1 && !ls[v - 1]) {
                    isa[buf[s[v - 1]]++] = v - 1;
                }
            }
            copy(sum_l.begin(), sum_l.end(), buf.begin());
            for (int i = N - 1; i >= 0; --i) {
                int v = isa[i];
                if (v >= 1 && ls[v - 1]) {
                    isa[--buf[s[v - 1] + 1]] = v - 1;
                }
            }
        };
            
        vector<int> lms, lms_map(N + 1, -1);
        int M = 0;
        for (int i = 1; i < N; ++i) {
            if (!ls[i - 1] && ls[i]) {
                lms_map[i] = M++;
            }
        }
        lms.reserve(M);
        for (int i = 1; i < N; ++i) {
            if (!ls[i - 1] && ls[i]) {
                lms.push_back(i);
            }
        }
        induce(lms);

        if (M) {
            vector<int> lms2;
            lms2.reserve(isa.size());
            for (auto v: isa) {
                if (lms_map[v] != -1) lms2.push_back(v);
            }
            int rec_upper = 0;
            vector<int> rec_s(M);
            rec_s[lms_map[lms2[0]]] = 0;
            for (int i = 1; i < M; ++i) {
                int l = lms2[i - 1], r = lms2[i];
                int nl = (lms_map[l] + 1 < M) ? lms[lms_map[l] + 1] : N;
                int nr = (lms_map[r] + 1 < M) ? lms[lms_map[r] + 1] : N;
                bool same = true;
                if (nl - l != nr - r) same = false;
                else {
                    while (l < nl) {
                        if (s[l] != s[r]) break;
                        ++l, ++r;
                    }
                    if (l == N || s[l] != s[r]) same = false;
                }
                if (!same) ++rec_upper;
                rec_s[lms_map[lms2[i]]] = rec_upper;
            }
            auto rec_sa = sa_is(rec_s, rec_upper);

            vector<int> sorted_lms(M);
            for (int i = 0; i < M; ++i) {
                sorted_lms[i] = lms[rec_sa[i]];
            }
            induce(sorted_lms);
        }
        return isa;
    }

    // find min id that str.substr(sa[id]) >= T
    int lower_bound(const Str& T) {
        int left = -1, right = sa.size();
        while (right - left > 1) {
            int mid = (left + right) / 2;
            if (str.compare(sa[mid], string::npos, T) < 0)
                left = mid;
            else
                right = mid;
        }
        return right;
    }

    // find min id that str.substr(sa[id], T.size()) > T
    int upper_bound(const Str& T) {
        int left = -1, right = sa.size();
        while (right - left > 1) {
            int mid = (left + right) / 2;
            if (str.compare(sa[mid], T.size(), T) <= 0)
                left = mid;
            else
                right = mid;
        }
        return right;
    }

    // search
    bool is_contain(const Str& T) {
        int lb = lower_bound(T);
        if (lb >= sa.size()) return false;
        return str.compare(sa[lb], T.size(), T) == 0;
    }

    // find lcp
    void calcLCP(const vector<int> &s) {
        int N = (int)s.size();
        rank.assign(N, 0), lcp.assign(N, 0);
        for (int i = 0; i < N; ++i) rank[sa[i]] = i;
        int h = 0;
        for (int i = 0; i < N - 1; ++i) {
            int pi = sa[rank[i] - 1];
            if (h > 0) --h;
            for (; pi + h < N && i + h < N; ++h) {
                if (s[pi + h] != s[i + h]) break;
            }
            lcp[rank[i] - 1] = h;
        }
    }
    
    // build sparse table for calculating lcp
    void buildSparseTable() {
        st.init(lcp);
    }

    // calc lcp of str.sutstr(a) and str.substr(b)
    int getLCP(int a, int b) {
        return st.get(min(rank[a], rank[b]), max(rank[a], rank[b]));
    }
};

void solveAOJ2644() {
    // Suffix Array の構築
    string S;
    cin >> S;
    SuffixArray<string> suf(S);
    vector<int> sa = suf.get_sa();

    // Suffix Array の区間に関する RMQ
    SparseTable<int> min_st(sa);
    for (auto& v : sa) v = -v;
    SparseTable<int> max_st(sa);

    auto solve = [&](const string& x, const string& y) -> int {
        if (!suf.is_contain(x) || !suf.is_contain(y)) {
            return 0;
        }
        int xl = suf.lower_bound(x);
        int xr = suf.upper_bound(x);
        int yl = suf.lower_bound(y);
        int yr = suf.upper_bound(y);
        int xres = min_st.get(xl, xr);
        int yres = -max_st.get(yl, yr);

        if (xres > yres || xres + x.size() > yres + y.size()) 
            return 0;
        else 
            return yres - xres + (int)y.size();   
    };

    int Q;
    cin >> Q;
    while (Q--) {
        string x, y;
        cin >> x >> y;
        cout << solve(x, y) << endl;
    }
}

int main() {
    solveAOJ2644();
}
accuracy: 1
time_ms: 170
memory_kb: 65820
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;

// Sparse Table
template<class MeetSemiLattice> struct SparseTable {
    vector<vector<MeetSemiLattice> > dat;
    vector<int> height;
    
    SparseTable() { }
    SparseTable(const vector<MeetSemiLattice> &vec) { init(vec); }
    void init(const vector<MeetSemiLattice> &vec) {
        int n = (int)vec.size(), h = 0;
        while ((1<<h) < n) ++h;
        dat.assign(h, vector<MeetSemiLattice>(1<<h));
        height.assign(n+1, 0);
        for (int i = 2; i <= n; i++) height[i] = height[i>>1]+1;
        for (int i = 0; i < n; ++i) dat[0][i] = vec[i];
        for (int i = 1; i < h; ++i)
            for (int j = 0; j < n; ++j)
                dat[i][j] = min(dat[i-1][j], dat[i-1][min(j+(1<<(i-1)),n-1)]);
    }
    
    MeetSemiLattice get(int a, int b) {
        return min(dat[height[b-a]][a], dat[height[b-a]][b-(1<<height[b-a])]);
    }
};

// SA-IS (O(N))
template<class Str> struct SuffixArray {
    // data
    Str str;
    vector<int> sa;    // sa[i] : the starting index of the i-th smallest suffix (i = 0, 1, ..., n)
    vector<int> rank;  // rank[sa[i]] = i
    vector<int> lcp;   // lcp[i]: the lcp of sa[i] and sa[i+1] (i = 0, 1, ..., n-1)
    SparseTable<int> st;  // use for calcultating lcp(i, j)

    // getter
    int& operator [] (int i) {
        return sa[i];
    }
    vector<int> get_sa() { return sa; }
    vector<int> get_rank() { return rank; }
    vector<int> get_lcp() { return lcp; }

    // constructor
    SuffixArray(const Str& str_) : str(str_) {
        build_sa();
    }
    void init(const Str& str_) {
        str = str_;
        build_sa();
    }
    void build_sa() {
        vector<int> s;
        for (int i = 0; i < (int)str.size(); ++i) {
            s.push_back(str[i] + 1);
        }
        s.push_back(0);
        sa = sa_is(s);
        calcLCP(s);
        buildSparseTable();
    }

    // SA-IS
    // upper: # of characters 
    vector<int> sa_is(vector<int> &s, int upper = 256) {
        int N = (int)s.size();
        if (N == 0) return {};
        else if (N == 1) return {0};
        else if (N == 2) {
            if (s[0] < s[1]) return {0, 1};
            else return {1, 0};
        }

        vector<int> isa(N);
        vector<bool> ls(N, false);
        for (int i = N - 2; i >= 0; --i) {
            ls[i] = (s[i] == s[i + 1]) ? ls[i + 1] : (s[i] < s[i + 1]);
        }
        vector<int> sum_l(upper + 1, 0), sum_s(upper + 1, 0);
        for (int i = 0; i < N; ++i) {
            if (!ls[i]) ++sum_s[s[i]];
            else ++sum_l[s[i] + 1];
        }
        for (int i = 0; i <= upper; ++i) {
            sum_s[i] += sum_l[i];
            if (i < upper) sum_l[i + 1] += sum_s[i];
        }

        auto induce = [&](const vector<int> &lms) -> void {
            fill(isa.begin(), isa.end(), -1);
            vector<int> buf(upper + 1);
            copy(sum_s.begin(), sum_s.end(), buf.begin());
            for (auto d: lms) {
                if (d == N) continue;
                isa[buf[s[d]]++] = d;
            }
            copy(sum_l.begin(), sum_l.end(), buf.begin());
            isa[buf[s[N - 1]]++] = N - 1;
            for (int i = 0; i < N; ++i) {
                int v = isa[i];
                if (v >= 1 && !ls[v - 1]) {
                    isa[buf[s[v - 1]]++] = v - 1;
                }
            }
            copy(sum_l.begin(), sum_l.end(), buf.begin());
            for (int i = N - 1; i >= 0; --i) {
                int v = isa[i];
                if (v >= 1 && ls[v - 1]) {
                    isa[--buf[s[v - 1] + 1]] = v - 1;
                }
            }
        };
            
        vector<int> lms, lms_map(N + 1, -1);
        int M = 0;
        for (int i = 1; i < N; ++i) {
            if (!ls[i - 1] && ls[i]) {
                lms_map[i] = M++;
            }
        }
        lms.reserve(M);
        for (int i = 1; i < N; ++i) {
            if (!ls[i - 1] && ls[i]) {
                lms.push_back(i);
            }
        }
        induce(lms);

        if (M) {
            vector<int> lms2;
            lms2.reserve(isa.size());
            for (auto v: isa) {
                if (lms_map[v] != -1) lms2.push_back(v);
            }
            int rec_upper = 0;
            vector<int> rec_s(M);
            rec_s[lms_map[lms2[0]]] = 0;
            for (int i = 1; i < M; ++i) {
                int l = lms2[i - 1], r = lms2[i];
                int nl = (lms_map[l] + 1 < M) ? lms[lms_map[l] + 1] : N;
                int nr = (lms_map[r] + 1 < M) ? lms[lms_map[r] + 1] : N;
                bool same = true;
                if (nl - l != nr - r) same = false;
                else {
                    while (l < nl) {
                        if (s[l] != s[r]) break;
                        ++l, ++r;
                    }
                    if (l == N || s[l] != s[r]) same = false;
                }
                if (!same) ++rec_upper;
                rec_s[lms_map[lms2[i]]] = rec_upper;
            }
            auto rec_sa = sa_is(rec_s, rec_upper);

            vector<int> sorted_lms(M);
            for (int i = 0; i < M; ++i) {
                sorted_lms[i] = lms[rec_sa[i]];
            }
            induce(sorted_lms);
        }
        return isa;
    }

    // find min id that str.substr(sa[id]) >= T
    int lower_bound(const string& T) {
        int left = -1, right = sa.size();
        while (right - left > 1) {
            int mid = (left + right) / 2;
            if (str.compare(sa[mid], string::npos, T) < 0)
                left = mid;
            else
                right = mid;
        }
        return right;
    }

    // find min id that str.substr(sa[id], T.size()) > T
    int upper_bound(const string& T) {
        int left = -1, right = sa.size();
        while (right - left > 1) {
            int mid = (left + right) / 2;
            if (str.compare(sa[mid], T.size(), T) <= 0)
                left = mid;
            else
                right = mid;
        }
        return right;
    }

    // search
    bool is_contain(const string& T) {
        int lb = lower_bound(T);
        if (lb >= sa.size()) return false;
        return str.compare(sa[lb], T.size(), T) == 0;
    }

    // find lcp
    void calcLCP(const vector<int> &s) {
        int N = (int)s.size();
        rank.assign(N, 0), lcp.assign(N, 0);
        for (int i = 0; i < N; ++i) rank[sa[i]] = i;
        int h = 0;
        for (int i = 0; i < N - 1; ++i) {
            int pi = sa[rank[i] - 1];
            if (h > 0) --h;
            for (; pi + h < N && i + h < N; ++h) {
                if (s[pi + h] != s[i + h]) break;
            }
            lcp[rank[i] - 1] = h;
        }
    }
    
    // build sparse table for calculating lcp
    void buildSparseTable() {
        st.init(lcp);
    }

    // calc lcp of str.sutstr(a) and str.substr(b)
    int getLCP(int a, int b) {
        return st.get(min(rank[a], rank[b]), max(rank[a], rank[b]));
    }
};

void solveAOJ2644() {
    // Suffix Array の構築
    string S;
    cin >> S;
    SuffixArray<string> suf(S);
    vector<int> sa = suf.get_sa();

    // Suffix Array の区間に関する RMQ
    SparseTable<int> min_st(sa);
    for (auto& v : sa) v = -v;
    SparseTable<int> max_st(sa);

    auto solve = [&](const string& x, const string& y) -> int {
        if (!suf.is_contain(x) || !suf.is_contain(y)) {
            return 0;
        }
        int xl = suf.lower_bound(x);
        int xr = suf.upper_bound(x);
        int yl = suf.lower_bound(y);
        int yr = suf.upper_bound(y);
        int xres = min_st.get(xl, xr);
        int yres = -max_st.get(yl, yr);

        if (xres > yres || xres + x.size() > yres + y.size()) 
            return 0;
        else 
            return yres - xres + (int)y.size();   
    };

    int Q;
    cin >> Q;
    while (Q--) {
        string x, y;
        cin >> x >> y;
        cout << solve(x, y) << endl;
    }
}

int main() {
    solveAOJ2644();
}
accuracy: 1
time_ms: 180
memory_kb: 65856
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define REP(i, n) for (long long i = 0; i < (long long)(n); ++i)
#define REP2(i, a, b) for (long long i = a; i < (long long)(b); ++i)
#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P)
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, deque<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, vector<vector<T> > P)
{ for (int i = 0; i < P.size(); ++i) { s << endl << P[i]; } return s << endl; }
template<class T> ostream& operator << (ostream &s, set<T> P)
{ for(auto it : P) { s << "<" << it << "> "; } return s; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P)
{ for(auto it : P) { s << "<" << it.first << "->" << it.second << "> "; } return s; }



// Sparse Table
template<class MeetSemiLattice> struct SparseTable {
    vector<vector<MeetSemiLattice> > dat;
    vector<int> height;
    
    SparseTable() { }
    SparseTable(const vector<MeetSemiLattice> &vec) { init(vec); }
    void init(const vector<MeetSemiLattice> &vec) {
        int n = (int)vec.size(), h = 0;
        while ((1<<h) < n) ++h;
        dat.assign(h, vector<MeetSemiLattice>(1<<h));
        height.assign(n+1, 0);
        for (int i = 2; i <= n; i++) height[i] = height[i>>1]+1;
        for (int i = 0; i < n; ++i) dat[0][i] = vec[i];
        for (int i = 1; i < h; ++i)
            for (int j = 0; j < n; ++j)
                dat[i][j] = min(dat[i-1][j], dat[i-1][min(j+(1<<(i-1)),n-1)]);
    }
    
    MeetSemiLattice get(int a, int b) {
        return min(dat[height[b-a]][a], dat[height[b-a]][b-(1<<height[b-a])]);
    }
};

// SA-IS (O(N))
template<class Str> struct SuffixArray {
    // data
    Str str;
    vector<int> sa;    // sa[i] : the starting index of the i-th smallest suffix (i = 0, 1, ..., n)
    vector<int> rank;  // rank[sa[i]] = i
    vector<int> lcp;   // lcp[i]: the lcp of sa[i] and sa[i+1] (i = 0, 1, ..., n-1)
    SparseTable<int> st;  // use for calcultating lcp(i, j)

    // getter
    int& operator [] (int i) {
        return sa[i];
    }
    vector<int> get_sa() { return sa; }
    vector<int> get_rank() { return rank; }
    vector<int> get_lcp() { return lcp; }

    // constructor
    SuffixArray(const Str& str_) : str(str_) {
        build_sa();
    }
    void init(const Str& str_) {
        str = str_;
        build_sa();
    }
    void build_sa() {
        vector<int> s;
        for (int i = 0; i < (int)str.size(); ++i) {
            s.push_back(str[i] + 1);
        }
        s.push_back(0);
        sa = sa_is(s);
        calcLCP(s);
        buildSparseTable();
    }

    // SA-IS
    // upper: # of characters 
    vector<int> sa_is(vector<int> &s, int upper = 256) {
        int N = (int)s.size();
        if (N == 0) return {};
        else if (N == 1) return {0};
        else if (N == 2) {
            if (s[0] < s[1]) return {0, 1};
            else return {1, 0};
        }

        vector<int> isa(N);
        vector<bool> ls(N, false);
        for (int i = N - 2; i >= 0; --i) {
            ls[i] = (s[i] == s[i + 1]) ? ls[i + 1] : (s[i] < s[i + 1]);
        }
        vector<int> sum_l(upper + 1, 0), sum_s(upper + 1, 0);
        for (int i = 0; i < N; ++i) {
            if (!ls[i]) ++sum_s[s[i]];
            else ++sum_l[s[i] + 1];
        }
        for (int i = 0; i <= upper; ++i) {
            sum_s[i] += sum_l[i];
            if (i < upper) sum_l[i + 1] += sum_s[i];
        }

        auto induce = [&](const vector<int> &lms) -> void {
            fill(isa.begin(), isa.end(), -1);
            vector<int> buf(upper + 1);
            copy(sum_s.begin(), sum_s.end(), buf.begin());
            for (auto d: lms) {
                if (d == N) continue;
                isa[buf[s[d]]++] = d;
            }
            copy(sum_l.begin(), sum_l.end(), buf.begin());
            isa[buf[s[N - 1]]++] = N - 1;
            for (int i = 0; i < N; ++i) {
                int v = isa[i];
                if (v >= 1 && !ls[v - 1]) {
                    isa[buf[s[v - 1]]++] = v - 1;
                }
            }
            copy(sum_l.begin(), sum_l.end(), buf.begin());
            for (int i = N - 1; i >= 0; --i) {
                int v = isa[i];
                if (v >= 1 && ls[v - 1]) {
                    isa[--buf[s[v - 1] + 1]] = v - 1;
                }
            }
        };
            
        vector<int> lms, lms_map(N + 1, -1);
        int M = 0;
        for (int i = 1; i < N; ++i) {
            if (!ls[i - 1] && ls[i]) {
                lms_map[i] = M++;
            }
        }
        lms.reserve(M);
        for (int i = 1; i < N; ++i) {
            if (!ls[i - 1] && ls[i]) {
                lms.push_back(i);
            }
        }
        induce(lms);

        if (M) {
            vector<int> lms2;
            lms2.reserve(isa.size());
            for (auto v: isa) {
                if (lms_map[v] != -1) lms2.push_back(v);
            }
            int rec_upper = 0;
            vector<int> rec_s(M);
            rec_s[lms_map[lms2[0]]] = 0;
            for (int i = 1; i < M; ++i) {
                int l = lms2[i - 1], r = lms2[i];
                int nl = (lms_map[l] + 1 < M) ? lms[lms_map[l] + 1] : N;
                int nr = (lms_map[r] + 1 < M) ? lms[lms_map[r] + 1] : N;
                bool same = true;
                if (nl - l != nr - r) same = false;
                else {
                    while (l < nl) {
                        if (s[l] != s[r]) break;
                        ++l, ++r;
                    }
                    if (l == N || s[l] != s[r]) same = false;
                }
                if (!same) ++rec_upper;
                rec_s[lms_map[lms2[i]]] = rec_upper;
            }
            auto rec_sa = sa_is(rec_s, rec_upper);

            vector<int> sorted_lms(M);
            for (int i = 0; i < M; ++i) {
                sorted_lms[i] = lms[rec_sa[i]];
            }
            induce(sorted_lms);
        }
        return isa;
    }

    // find min id that str.substr(sa[id]) >= T
    int lower_bound(const string& T) {
        int left = -1, right = sa.size();
        while (right - left > 1) {
            int mid = (left + right) / 2;
            if (str.compare(sa[mid], string::npos, T) < 0)
                left = mid;
            else
                right = mid;
        }
        return right;
    }

    // find min id that str.substr(sa[id], T.size()) > T
    int upper_bound(const string& T) {
        int left = -1, right = sa.size();
        while (right - left > 1) {
            int mid = (left + right) / 2;
            if (str.compare(sa[mid], T.size(), T) <= 0)
                left = mid;
            else
                right = mid;
        }
        return right;
    }

    // search
    bool is_contain(const string& T) {
        int lb = lower_bound(T);
        if (lb >= sa.size()) return false;
        return str.compare(sa[lb], T.size(), T) == 0;
    }

    // find lcp
    void calcLCP(const vector<int> &s) {
        int N = (int)s.size();
        rank.assign(N, 0), lcp.assign(N, 0);
        for (int i = 0; i < N; ++i) rank[sa[i]] = i;
        int h = 0;
        for (int i = 0; i < N - 1; ++i) {
            int pi = sa[rank[i] - 1];
            if (h > 0) --h;
            for (; pi + h < N && i + h < N; ++h) {
                if (s[pi + h] != s[i + h]) break;
            }
            lcp[rank[i] - 1] = h;
        }
    }
    
    // build sparse table for calculating lcp
    void buildSparseTable() {
        st.init(lcp);
    }

    // calc lcp of str.sutstr(a) and str.substr(b)
    int getLCP(int a, int b) {
        return st.get(min(rank[a], rank[b]), max(rank[a], rank[b]));
    }
};

int main() {
    // Suffix Array の構築
    string S;
    cin >> S;
    SuffixArray<string> suf(S);
    vector<int> sa = suf.get_sa();

    //for (int i = 0; i <= S.size(); ++i) cout << i << ": " << sa[i] <<

    // Suffix Array の区間に関する RMQ
    SparseTable<int> min_st(sa);
    for (auto& v : sa) v = -v;
    SparseTable<int> max_st(sa);

    auto solve = [&](const string& x, const string& y) -> int {
        if (!suf.is_contain(x) || !suf.is_contain(y)) {
            return 0;
        }
        int xl = suf.lower_bound(x);
        int xr = suf.upper_bound(x);
        int yl = suf.lower_bound(y);
        int yr = suf.upper_bound(y);
        int xres = min_st.get(xl, xr);
        int yres = -max_st.get(yl, yr);

        //cout << x << ", " << y << ": " << make_pair(xl, xr) << ", " << make_pair(yl, yr) << ":: " << xres << ", " << yres << endl;
        if (xres > yres || xres + x.size() > yres + y.size()) 
            return 0;
        else 
            return yres - xres + (int)y.size();   
    };

    int Q;
    cin >> Q;
    while (Q--) {
        string x, y;
        cin >> x >> y;
        cout << solve(x, y) << endl;
    }
}
accuracy: 1
time_ms: 180
memory_kb: 65848
final_rank: 12

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, n) for (int i = 0; i < (n); ++i)
#define rrep(i, n) for (int i = (n) - 1; i >= 0; --i)

#define all(v) (v).begin(), (v).end()

template <typename ...Args>
void read(Args&... args) {
    (cin >> ... >> args);
}

template <typename T>
istream& operator>>(istream& in, vector<T>& v) {
    for (auto& e : v) in >> e;
    return in;
}

template <typename T>
ostream& operator<<(ostream& out, const vector<T>& v) {
    int n = v.size();
    for (int i = 0; i < n; ++i) {
        out << v[i];
        if (i + 1 != n) out << ' ';
    }
    return out;
}

template <typename Head, typename ...Tails>
void print(const Head& h, const Tails &... tail) {
    cout << h;
    if constexpr (sizeof...(tail)) {
        cout << ' ';
        print(tail...);
    }
}
template <typename ...Args>
void println(const Args &... args) {
    print(args...);
    print('\n');
}

template <typename T>
bool chmin(T& x, const T& y) {
    if (y < x) {
        x = y;
        return true;
    }
    return false;
}
template <typename T>
bool chmax(T& x, const T& y) {
    if (y > x) {
        x = y;
        return true;
    }
    return false;
}

constexpr int iinf = numeric_limits<int>::max() / 2;

class suffix_array {
    const int n;
    string S;
    vector<int> sa, rank;
public:
    suffix_array(const string& S_) : n(S_.size()), S(S_), sa(n + 1), rank(n + 1) {
        for (int i = 0; i <= n; ++i) {
            sa[i] = i;
            rank[i] = i < n ? S[i] : -1;
        }
        vector<int> tmp(n + 1);
        for (int k = 1;k <= n; k *= 2) {
            auto Compare_SA = [=](int i, int j) {
                if (rank[i] != rank[j]) return rank[i] < rank[j];
                int ri = i + k <= n ? rank[i + k] : -1;
                int rj = j + k <= n ? rank[j + k] : -1;
                return ri < rj;
            };
            sort(all(sa), Compare_SA);
            tmp[sa[0]] = 0;
            for (int i = 1; i <= n; ++i) {
                tmp[sa[i]] = tmp[sa[i - 1]] + (Compare_SA(sa[i - 1], sa[i]) ? 1 : 0);
            }
            for (int i = 0; i <= n; ++i) {
                rank[i] = tmp[i];
            }
        }
    }
    int& operator[](int i) {
        return sa[i];
    }
    vector<int> get_lcp() {
        for (int i = 0; i <= n; ++i) rank[sa[i]] = i;
        int h = 0;
        vector<int> lcp(n + 1);
        for (int i = 0; i < n; ++i) {
            int j = sa[rank[i] - 1];
            if (h > 0) --h;
            for (; j + h < n and i + h < n; ++h) {
                if (S[j + h] != S[i + h]) break;
            }
            lcp[rank[i] - 1] = h;
        }
        return lcp;
    }
};

template <typename T, T(*op)(T, T), T(*e)()>
struct segtree {
    int _n;
    int siz;
    vector<T> dat;
    segtree(int n = 0) : segtree(n, vector<T>(n, e())) {}
    segtree(vector<T> a) : _n(a.size()) {
        int n = a.size();
        siz = 1;
        while (siz < n) siz <<= 1;
        dat = vector<T>(2 * siz, e());
        for (int i = 0; i < n; ++i) {
            dat[siz + i] = a[i];
        }
        for (int i = siz - 1; i; --i) {
            dat[i] = op(dat[2 * i], dat[2 * i + 1]);
        }
    }

    T prod(int l, int r) const {
        assert(0 <= l and l <= r and r <= _n);

        T sml = e(), smr = e();
        for (l += siz, r += siz; l < r; l >>= 1, r >>= 1) {
            if (l & 1) sml = op(sml, dat[l++]);
            if (r & 1) smr = op(dat[--r], smr);
        }
        return op(sml, smr);
    }

    T all_prod() const {
        return dat[1];
    }

    void set(int i, T v) {
        assert(0 <= i and i < _n);
        i += siz;
        dat[i] = v;
        for (i >>= 1; i; i >>= 1) {
            dat[i] = op(dat[2 * i], dat[2 * i + 1]);
        }
    }
};

namespace maxseg {
    int op(int x, int y) {
        return max(x, y);
    }
    int e() {
        return -1;
    }
}
namespace minseg {
    int op(int x, int y) {
        return min(x, y);
    }
    int e() {
        return 10000000;
    }
}
using RMQ = segtree<int, maxseg::op, maxseg::e>;
using RmQ = segtree<int, minseg::op, minseg::e>;

int main() {
    string s;
    read(s);

    const int n = s.size();

    int m;
    read(m);

    s += '$';
    
    vector<array<string, 2>> qs(m);

    vector<array<int, 2>> qs_pos(m);
    rep(i, m) {
        read(qs[i][0], qs[i][1]);
        qs_pos[i][0] = s.size();
        s += qs[i][0];
        qs_pos[i][1] = s.size();
        s += qs[i][1];
    }

    int l = s.size();

    suffix_array sa_(s);

    vector<int> lcp = sa_.get_lcp();

    vector<int> sa(l);
    rep(i, l) {
        sa[i] = sa_[i + 1];
    }
    lcp.erase(lcp.begin());
    lcp.pop_back();
    
    vector<int> sa_inv(l);
    rep(i, l) {
        sa_inv[sa[i]] = i;
    }

    vector<int> RMQinit(l), RmQinit(l);
    rep(i, l) {
        RMQinit[i] = sa[i] >= n ? maxseg::e() : sa[i];
        RmQinit[i] = sa[i] >= n ? minseg::e() : sa[i];
    }

    RmQ min_lcp(lcp);

    RMQ max_seg(RMQinit);
    RmQ min_seg(RmQinit);

    auto get_range = [&](int i, int len) -> pair<int, int> {
        int ctr = sa_inv[i];

        auto max_right = [&]() {
            int ok = ctr, ng = l;
            while (abs(ng - ok) > 1) {
                int mid = (ng + ok) >> 1;
                (min_lcp.prod(ctr, mid) >= len ? ok : ng) = mid;
            }
            return ok;
        };
        auto min_left = [&]() {
            int ng = -1, ok = ctr;
            while (abs(ng - ok) > 1) {
                int mid = (ng + ok) >> 1;
                (min_lcp.prod(mid, ctr) >= len ? ok : ng) = mid;
            }
            return ok;
        };

        return { min_left(), max_right() + 1 };
    };

    rep(i, m) {
        int len_p = qs[i][0].size();
        int len_s = qs[i][1].size();

        auto [l0, r0] = get_range(qs_pos[i][0], len_p);
        auto [l1, r1] = get_range(qs_pos[i][1], len_s);

        // println("debug", i);
        // println(l0, r0);
        // println(l1, r1);

        int fr = min_seg.prod(l0, r0);
        int to = max_seg.prod(l1, r1) + len_s;

        if (to - fr >= max(len_p, len_s)) {
            println(to - fr);
        } else { 
            println(0);
        }
    }
}
accuracy: 1
time_ms: 640
memory_kb: 35708
final_rank: 14

code_snippet: #include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <iomanip>
#include <iostream>
#include <utility>
#include <vector>

namespace luz {

  using isize = std::ptrdiff_t;
  using usize = std::size_t;

  using i32 = std::int32_t;
  using i64 = std::int64_t;
  using u32 = std::uint32_t;
  using u64 = std::uint64_t;
  
} // namespace luz

namespace luz {

  struct rep {
    struct itr {
      usize i;
      constexpr itr(const usize i) noexcept : i(i) {}
      void operator++() noexcept { ++i; }
      constexpr usize operator*() const noexcept { return i; }
      constexpr bool operator!=(const itr x) const noexcept { return i != x.i; }
    };
    const itr f, l;
    constexpr rep(const usize f, const usize l) noexcept
      : f(std::min(f, l)), l(l) {}
    constexpr auto begin() const noexcept { return f; }
    constexpr auto end() const noexcept { return l; }
  };

  struct rrep {
    struct itr {
      usize i;
      constexpr itr(const usize i) noexcept : i(i) {}
      void operator++() noexcept { --i; }
      constexpr usize operator*() const noexcept { return i; }
      constexpr bool operator!=(const itr x) const noexcept { return i != x.i; }
    };
    const itr f, l;
    constexpr rrep(const usize f, const usize l) noexcept
      : f(l - 1), l(std::min(f, l) - 1) {}
    constexpr auto begin() const noexcept { return f; }
    constexpr auto end() const noexcept { return l; }
  };

} // namespace luz

namespace luz {

  void set_fast_ios() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
  }

} // namespace luz

namespace luz {

  void io_set(usize precision) {
    std::cout << std::fixed << std::setprecision(precision);
    std::cerr << std::fixed << std::setprecision(precision);
  }

} // namespace luz

namespace luz {

  template< typename T = i64 > T input() {
    T tmp;
    std::cin >> tmp;
    return tmp;
  }

} // namespace luz

namespace luz {

  template< typename T >
  std::ostream &operator<<(std::ostream &os, std::vector< T > &vs) {
    for (usize i: rep(0, vs.size())) {
      os << vs[i] << (i + 1 != vs.size() ? " " : "");
    }
    return os;
  }

  template< typename T >
  std::istream &operator>>(std::istream &is, std::vector< T > &vs) {
    for (T &v: vs) {
      is >> v;
    }
    return is;
  }

} // namespace luz

namespace luz {

  template< typename T1, typename T2 >
  std::ostream &operator<<(std::ostream &os, std::pair < T1, T2 > &p) {
    os << "(" << p.first << ", " << p.second << ")";
    return os;
  }

  template< typename T1, typename T2 >
  std::istream &operator>>(std::istream &is, std::pair< T1, T2 > &p) {
    is >> p.first >> p.second;
    return is;
  }

} // namespace luz

namespace luz {

  template <typename T>
  std::vector<T> make_vector(usize a, T b) {
    return std::vector<T>(a, b);
  }

  template <typename... Ts>
  auto make_vector(usize a, Ts... ts) {
    return std::vector<decltype(make_vector(ts...))>(a, make_vector(ts...));
  }

} // namespace luz

namespace luz {

  template <typename T1, typename T2>
  inline bool chmax(T1 &a, T2 b) {
    return a < b and (a = b, true);
  }

  template <typename T1, typename T2>
  inline bool chmin(T1 &a, T2 b) {
    return a > b and (a = b, true);
  }

} // namespace luz

using namespace std;
#include <numeric>
/**
 * @brief Suffix Array(接尾辞配列)
 */
template< typename T >
struct SuffixArray : vector< int > {
private:
  vector< int > sa_is(const vector< int > &s) const {
    const int n = (int) s.size();
    vector< int > ret(n);

    vector< int > is_s(n), is_lms(n);
    int m = 0;
    for(int i = n - 2; i >= 0; i--) {
      is_s[i] = (s[i] > s[i + 1]) or (s[i] == s[i + 1] and is_s[i + 1]);
      m += (is_lms[i + 1] = is_s[i] and not is_s[i + 1]);
    }

    auto induced_sort = [&](const vector< int > &lms) {
      int upper = *max_element(s.begin(), s.end());
      vector< int > l(upper + 2), r(upper + 2);
      for(auto &&v: s) {
        ++l[v + 1];
        ++r[v];
      }
      partial_sum(l.begin(), l.end(), l.begin());
      partial_sum(r.begin(), r.end(), r.begin());
      fill(ret.begin(), ret.end(), -1);
      for(int i = (int) lms.size() - 1; i >= 0; i--) {
        ret[--r[s[lms[i]]]] = lms[i];
      }
      for(auto &&v: ret) {
        if(v >= 1 and is_s[v - 1]) ret[l[s[v - 1]]++] = v - 1;
      }
      fill(r.begin(), r.end(), 0);
      for(auto &&v: s) ++r[v];
      partial_sum(r.begin(), r.end(), r.begin());
      for(int k = (int) ret.size() - 1, i = ret[k]; k >= 1; i = ret[--k]) {
        if(i >= 1 and not is_s[i - 1]) {
          ret[--r[s[i - 1]]] = i - 1;
        }
      }
    };

    vector< int > lms;
    lms.reserve(m);
    for(int i = 1; i < n; i++) {
      if(is_lms[i]) lms.push_back(i);
    }

    induced_sort(lms);

    vector< int > new_lms;
    new_lms.reserve(m);
    for(int i = 0; i < n; i++) {
      if(not is_s[ret[i]] and ret[i] > 0 and is_s[ret[i] - 1]) {
        new_lms.push_back(ret[i]);
      }
    }

    auto is_same = [&](int a, int b) {
      if(s[a++] != s[b++]) return false;
      for(;; ++a, ++b) {
        if(s[a] != s[b]) return false;
        if(is_lms[a] or is_lms[b]) return is_lms[a] and is_lms[b];
      }
    };

    int rank = 0;
    ret[n - 1] = 0;
    for(int i = 1; i < m; i++) {
      if(not is_same(new_lms[i - 1], new_lms[i])) ++rank;
      ret[new_lms[i]] = rank;
    }

    if(rank + 1 < m) {
      vector< int > new_s(m);
      for(int i = 0; i < m; i++) {
        new_s[i] = ret[lms[i]];
      }
      auto lms_sa = sa_is(new_s);
      for(int i = 0; i < m; i++) {
        new_lms[i] = lms[lms_sa[i]];
      }
    }

    induced_sort(new_lms);

    return ret;
  }

public:
  T vs;

  explicit SuffixArray(const T &vs, bool compress = false) : vs(vs) {
    vector< int > new_vs(vs.size() + 1);
    if(compress) {
      T xs = vs;
      sort(xs.begin(), xs.end());
      xs.erase(unique(xs.begin(), xs.end()), xs.end());
      for(int i = 0; i < (int) vs.size(); i++) {
        new_vs[i] = std::lower_bound(xs.begin(), xs.end(), vs[i]) - xs.begin() + 1;
      }
    } else {
      auto d = *min_element(vs.begin(), vs.end());
      for(int i = 0; i < (int) vs.size(); i++) {
        new_vs[i] = vs[i] - d + 1;
      }
    }
    auto ret = sa_is(new_vs);
    assign(ret.begin(), ret.end());
  }

  void output() const {
    for(int i = 0; i < size(); i++) {
      cout << i << ":[" << (*this)[i] << "]";
      for(int j = (*this)[i]; j < (int) vs.size(); j++) cout << " " << vs[j];
      cout << "\n";
    }
  }

  bool lt_substr(const string &t, int si = 0, int ti = 0) {
    int sn = (int) vs.size(), tn = (int) t.size();
    while(si < sn && ti < tn) {
      if(vs[si] < t[ti]) return true;
      if(vs[si] > t[ti]) return false;
      ++si, ++ti;
    }
    return si >= sn && ti < tn;
  }

  // t <= s[i,N) なる最小の i を返す O(|t| log |s|)
  int lower_bound(const T &t) {
    int ng = 0, ok = (int) size();
    while(ok - ng > 1) {
      int mid = (ok + ng) / 2;
      if(lt_substr(t, at(mid))) ng = mid;
      else ok = mid;
    }
    return ok;
  }

  // O(|t| log |s|)
  pair< int, int > equal_range(T &t) {
    int low = lower_bound(t);
    int ng = low - 1, ok = (int) size();
    t.back()++;
    while(ok - ng > 1) {
      int mid = (ok + ng) / 2;
      if(lt_substr(t, at(mid))) ng = mid;
      else ok = mid;
    }
    t.back()--;
    return {low, ok};
  }
};

template<>
void SuffixArray< string >::output() const {
  for(int i = 0; i < (int) size(); i++) {
    cout << i << ":[" << (*this)[i] << "] " << vs.substr((*this)[i]) << "\n";
  }
}

template< typename Semigroup, typename F >
struct DisjointSparseTable {
  const F f;
  vector< vector< Semigroup > > st;
  vector< int > lookup;

  DisjointSparseTable(const vector< Semigroup > &v, const F &f) : f(f) {
    int b = 0;
    while((1 << b) <= v.size()) ++b;
    st.resize(b, vector< Semigroup >(v.size(), Semigroup()));
    for(int i = 0; i < v.size(); i++) st[0][i] = v[i];
    for(int i = 1; i < b; i++) {
      int shift = 1 << i;
      for(int j = 0; j < v.size(); j += shift << 1) {
        int t = min(j + shift, (int) v.size());
        st[i][t - 1] = v[t - 1];
        for(int k = t - 2; k >= j; k--) st[i][k] = f(v[k], st[i][k + 1]);
        if(v.size() <= t) break;
        st[i][t] = v[t];
        int r = min(t + shift, (int) v.size());
        for(int k = t + 1; k < r; k++) st[i][k] = f(st[i][k - 1], v[k]);
      }
    }
    lookup.resize(1 << b);
    for(int i = 2; i < lookup.size(); i++) {
      lookup[i] = lookup[i >> 1] + 1;
    }
  }

  Semigroup fold(int l, int r) {
    if(l >= --r) return st[0][l];
    int p = lookup[l ^ r];
    return f(st[p][l], st[p][r]);
  }
};

template< typename SemiGroup, typename F >
DisjointSparseTable< SemiGroup, F > get_disjoint_sparse_table(const vector< SemiGroup >& v, const F& f) {
  return {v, f};
}

namespace luz {

  void main_() {
    std::string s = input<std::string>();

    SuffixArray sa(s);

    auto mnst = get_disjoint_sparse_table(sa, [](int a, int b) { return min(a, b); });
    auto mxst = get_disjoint_sparse_table(sa, [](int a, int b) { return max(a, b); });

    int m = input();
    for (usize _: rep(0, m)) {
      std::string x = input<std::string>();
      std::string y = input<std::string>();

      auto [xl, xr] = sa.equal_range(x);
      auto [yl, yr] = sa.equal_range(y);
      if (xl == xr or yl == yr) {
        std::cout << 0 << std::endl;
      } else if (std::max(xl, yl) > s.size()) {
        std::cout << 0 << std::endl;
      } else {
        int l = mnst.fold(xl, xr);
        int r = mxst.fold(yl, yr);

        int ans = r - l + y.size();
        if (r + y.size() < l + x.size()) {
          ans = 0;
        }

        if (s.size() < l + x.size()) ans = 0;
        if (s.size() < r + y.size()) ans = 0;

        std::cout << ans << std::endl;
      }
    }

  }

} // namespace luz

int main() {
  luz::set_fast_ios();
  luz::io_set(15);

  luz::main_();
}
accuracy: 1
time_ms: 110
memory_kb: 35276
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long int;
using ull = unsigned long long int;
using P = pair<ll, ll>;
using P3 = pair<ll, P>;
using PP = pair<P, P>;
constexpr int INF32 = 1 << 30;
constexpr ll INF64 = 1LL << 62;
constexpr ll MOD = 1000000007;
// constexpr ll MOD = 998244353;
constexpr int di[] = {0, 1, 0, -1};
constexpr int dj[] = {1, 0, -1, 0};
constexpr int di8[] = {0, 1, 1, 1, 0, -1, -1, -1};
constexpr int dj8[] = {1, 1, 0, -1, -1, -1, 0, 1};
constexpr double EPS = 1e-10;
const double PI = acos(-1);

#define ALL(v) (v).begin(),(v).end()
#define REP(i,n) for(int i=0,i_len=n; i<i_len; ++i)

template<typename T1,typename T2> bool chmax(T1 &a, T2 b) { if (a<b) { a=b; return 1; } return 0; }
template<typename T1,typename T2> bool chmin(T1 &a, T2 b) { if (b<a) { a=b; return 1; } return 0; }

template <class S, S (*op)(S, S), S (*e)()>
struct SegmentTree {
  private:
    int _n, size, log;
    vector<S> dat;
    void update(int k) { dat[k] = op(dat[2 * k], dat[2 * k + 1]); }

  public:
    SegmentTree() : SegmentTree(0) {}
    SegmentTree(int n) : SegmentTree(vector<S>(n, e())) {}
    SegmentTree(const vector<S>& v) : _n(int(v.size())) {
        log = 0;
        while ((1 << log) < _n) log++;
        size = 1 << log;
        dat = vector<S>(2 * size, e());
        for (int i = 0; i < _n; i++) dat[size + i] = v[i];
        for (int i = size - 1; i >= 1; i--) {
            update(i);
        }
    }
    // a[p] = x
    void set(int p, S x) {
        p += size;
        dat[p] = x;
        for (int i = 1; i <= log; i++) update(p >> i);
    }
    // return a[p]
    S get(int p) const {
        return dat[p + size];
    }
    // return op(a[l], ..., a[r-1])
    S prod(int l, int r) const {
        S sml = e(), smr = e();
        l += size;
        r += size;
        while (l < r) {
            if (l & 1) sml = op(sml, dat[l++]);
            if (r & 1) smr = op(dat[--r], smr);
            l >>= 1;
            r >>= 1;
        }
        return op(sml, smr);
    }
    S all_prod() const { return dat[1]; }
};

int op_min(int a, int b){return min(a, b);}
int op_max(int a, int b){return max(a, b);}
int e_min(){return 1<<30;}
int e_max(){return -1;}

vector<int> suffix_array(const string& str) {
    int n = str.size();
    vector<int> sa(n + 1), rank(n + 1, -1);  // sa[i] = 辞書順でi番目であるsuffixの開始位置
    iota(sa.begin(), sa.end(), 0);
    for (int i = 0; i < n; i++) rank[i] = str[i];
    int k;
    auto comp = [&](const int& i, const int& j) {
        if (rank[i] != rank[j]) {
            return rank[i] < rank[j];
        } else {
            int ri = i + k <= n ? rank[i + k] : -1;
            int rj = j + k <= n ? rank[j + k] : -1;
            return ri < rj;
        }
    };
    for (k = 1; k <= n; k <<= 1) {
        sort(sa.begin(), sa.end(), comp);
        vector<int> tmp(n + 1, 0);
        for (int i = 0; i < n; i++) {
            tmp[sa[i + 1]] = tmp[sa[i]];
            if (comp(sa[i], sa[i + 1])) tmp[sa[i + 1]]++;
        }
        rank = tmp;
    }
    return sa;
}

int find_right(const string& s, const string& t, vector<int>& sa) {
    int l = 0, r = int(s.size())+1;
    while (r - l > 1) {
        int mid = (l + r) / 2;
        if (s.substr(sa[mid], t.size()) <= t) {
            l = mid;
        } else {
            r = mid;
        }
    }
    if (s.substr(sa[l], t.size()) == t){
        return l;
    }else{
        return -1;
    }
}

int find_left(const string& s, const string& t, vector<int>& sa) {
    int l = 0, r = int(s.size());
    while (r - l > 1) {
        int mid = (l + r) / 2;
        if (s.substr(sa[mid], t.size()) < t) {
            l = mid;
        } else {
            r = mid;
        }
    }
    if (s.substr(sa[r], t.size()) == t){
        return r;
    }else{
        return -1;
    }
}


int solve(){
    string s;
    cin >> s;
    vector<int> sa = suffix_array(s);
    SegmentTree<int, op_min, e_min> segmin(sa);
    SegmentTree<int, op_max, e_max> segmax(sa);
    int m;
    cin >> m;
    for(int i=0;i<m;i++){
        string x, y;
        cin >> x >> y;
        int lx = find_left(s, x, sa);
        int rx = find_right(s, x, sa);
        int ly = find_left(s, y, sa);
        int ry = find_right(s, y, sa);
        if(lx == -1 || ly == -1){
            cout << 0 << "\n";
            continue;
        }
        int l = segmin.prod(lx, rx+1), r = segmax.prod(ly, ry+1);
        r += y.size();
        if(r-l >= int(max(x.size(), y.size()))){
            cout << r-l << "\n";
        }else{
            cout << 0 << "\n";
        }
    }
    return 0;
}

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    solve();
    // int T; cin >> T; REP(t,T) solve();
    // while(!solve());
    return 0;
}
accuracy: 1
time_ms: 170
memory_kb: 8908
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod=1000000007,MAX=200005,INF=1<<28;
const int mod1=998244353,mod2=1000000009;

ll ru1[MAX],ru2[MAX];

void init(int base1,int base2){
    ru1[0]=1;
    ru2[0]=1;
    for(int i=1;i<MAX;i++){
        ru1[i]=ru1[i-1]*base1%mod1;
        ru2[i]=ru2[i-1]*base2%mod2;
    }
}

struct Rollinghash{
    string S;
    int n;
    int base1;
    int base2;
    vector<ll> h1,h2;
    
    void make(string &T,int ba1,int ba2){
        S=T;
        n=S.size();
        h1.assign(n+1,0);
        h2.assign(n+1,0);
        base1=ba1;
        base2=ba2;
        
        for(int i=1;i<=n;i++){
            h1[i]=h1[i-1]*base1+ll(S[i-1]-'a');
            h1[i]%=mod1;
            
            h2[i]=h2[i-1]*base2+ll(S[i-1]-'a');
            h2[i]%=mod2;
        }
    }
    
    pair<ll,ll> ha(int l,int r){
        pair<ll,ll> res;
        res.fi=(h1[r]-h1[l]*ru1[r-l]%mod1+mod1)%mod1;
        res.se=(h2[r]-h2[l]*ru2[r-l]%mod2+mod2)%mod2;
        
        return res;
    }//開区間
};

const int D=10;
vector<pair<pair<int,int>,int>> LL[D+1],RR[D+1];

int main(){
    
    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    ll ha1=37,ha2=43;
    init(ha1,ha2);
    string S;cin>>S;int Q;cin>>Q;
    Rollinghash ro;ro.make(S,ha1,ha2);
    int N=si(S);
    for(int len=1;len<=D;len++){
        map<pair<int,int>,int> L,R;
        for(int i=0;i+len<=N;i++){
            int j=i+len;
            auto x=ro.ha(i,j);
            if(L.count(x)==0) L[x]=i;
            R[x]=i;
        }
        for(auto a:L) LL[len].push_back(a);
        for(auto a:R) RR[len].push_back(a);
    }
    
    auto getha=[&](string &T){
        ll a=0,b=0;
        for(int i=1;i<=si(T);i++){
            a=a*ha1+ll(T[i-1]-'a');
            a%=mod1;
            
            b=b*ha2+ll(T[i-1]-'a');
            b%=mod2;
        }
        return mp(a,b);
    };
    
    auto id=[&](string &T){
        pair<int,int> x=getha(T);
        if(si(T)<=D){
            auto it=lower_bound(all(LL[si(T)]),mp(x,-1));
            if(it!=LL[si(T)].end()&&(*it).fi==x){
                auto it2=lower_bound(all(RR[si(T)]),mp(x,-1));
                return mp((*it).se,(*it2).se);
            }else{
                return mp(INF,-INF);
            }
        }else{
            int l=INF,r=-INF;
            for(int i=0;i+si(T)<=N;i++){
                if(ro.ha(i,i+si(T))==mp((ll)x.fi,(ll)x.se)){
                    chmin(l,i);
                    chmax(r,i);
                }
            }
            return mp(l,r);
        }
    };
    
    while(Q--){
        string A,B;cin>>A>>B;
        auto a=id(A),b=id(B);
        int ans=b.se+si(B)-a.fi;
        if(ans<max(si(A),si(B))) ans=0;
        cout<<ans<<"\n";
    }
}
accuracy: 1
time_ms: 1490
memory_kb: 74080
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;
const long long BASE = 1234567;
const long long MOD = 1000000007;
int main(){
  string S;
  cin >> S;
  int m;
  cin >> m;
  vector<string> x(m), y(m);
  for (int i = 0; i < m; i++){
    cin >> x[i] >> y[i];
  }
  int N = S.size();
  vector<long long> POW(N + 1);
  POW[0] = 1;
  for (int i = 0; i < N; i++){
    POW[i + 1] = POW[i] * BASE % MOD;
  }
  vector<long long> sum(N + 1);
  sum[N] = 0;
  for (int i = N - 1; i >= 0; i--){
    sum[i] = (sum[i + 1] * BASE + S[i]) % MOD;
  }
  vector<long long> hash1(m, 0), hash2(m, 0);
  for (int i = 0; i < m; i++){
    int sz1 = x[i].size();
    for (int j = 0; j < sz1; j++){
      hash1[i] += x[i][j] * POW[j];
      hash1[i] %= MOD;
    }
    int sz2 = y[i].size();
    for (int j = 0; j < sz2; j++){
      hash2[i] += y[i][j] * POW[j];
      hash2[i] %= MOD;
    }
  }
  vector<bool> ok(m, true);
  vector<vector<int>> idx(N + 1);
  vector<vector<int>> idy(N + 1);
  for (int i = 0; i < m; i++){
    if (x[i].size() <= N){
      idx[x[i].size()].push_back(i);
    } else {
      ok[i] = false;
    }
    if (y[i].size() <= N){
      idy[y[i].size()].push_back(i);
    } else {
      ok[i] = false;
    }
  }
  vector<int> l(m), r(m);
  for (int i = 1; i <= N; i++){
    if (!idx[i].empty() || !idy[i].empty()){
      vector<pair<long long, int>> P;
      for (int j = 0; j <= N - i; j++){
        long long hash = (sum[j] - sum[j + i] * POW[i] % MOD + MOD) % MOD;
        P.push_back(make_pair(hash, j));
      }
      sort(P.begin(), P.end());
      for (int j : idx[i]){
        auto itr = lower_bound(P.begin(), P.end(), make_pair(hash1[j], -1));
        if (itr == P.end()){
          ok[j] = false;
        } else if ((*itr).first != hash1[j]){
          ok[j] = false;
        } else {
          l[j] = (*itr).second;
        }
      }
      for (int j : idy[i]){
        auto itr = upper_bound(P.begin(), P.end(), make_pair(hash2[j], N));
        if (itr == P.begin()){
          ok[j] = false;
        } else {
          itr--;
          if ((*itr).first != hash2[j]){
            ok[j] = false;
          } else {
            r[j] = (*itr).second + y[j].size();
          }
        }
      }
    }
  }
  for (int i = 0; i < m; i++){
    if (!ok[i]){
      cout << 0 << endl;
    } else if (r[i] - l[i] < (int) max(x[i].size(), y[i].size())){
      cout << 0 << endl;
    } else {
      cout << r[i] - l[i] << endl;
    }
  }
}
accuracy: 1
time_ms: 1230
memory_kb: 33812
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;
const long long BASE = 1000000;
const long long MOD = 998244353;
int main(){
  string S;
  cin >> S;
  int m;
  cin >> m;
  vector<string> x(m), y(m);
  for (int i = 0; i < m; i++){
    cin >> x[i] >> y[i];
  }
  int N = S.size();
  vector<long long> POW(N + 1);
  POW[0] = 1;
  for (int i = 0; i < N; i++){
    POW[i + 1] = POW[i] * BASE % MOD;
  }
  vector<long long> sum(N + 1);
  sum[N] = 0;
  for (int i = N - 1; i >= 0; i--){
    sum[i] = (sum[i + 1] * BASE + S[i]) % MOD;
  }
  vector<long long> hash1(m, 0), hash2(m, 0);
  for (int i = 0; i < m; i++){
    int sz1 = x[i].size();
    for (int j = 0; j < sz1; j++){
      hash1[i] += x[i][j] * POW[j];
      hash1[i] %= MOD;
    }
    int sz2 = y[i].size();
    for (int j = 0; j < sz2; j++){
      hash2[i] += y[i][j] * POW[j];
      hash2[i] %= MOD;
    }
  }
  vector<bool> ok(m, true);
  vector<vector<int>> idx(N + 1);
  vector<vector<int>> idy(N + 1);
  for (int i = 0; i < m; i++){
    if (x[i].size() <= N){
      idx[x[i].size()].push_back(i);
    } else {
      ok[i] = false;
    }
    if (y[i].size() <= N){
      idy[y[i].size()].push_back(i);
    } else {
      ok[i] = false;
    }
  }
  vector<int> l(m), r(m);
  for (int i = 1; i <= N; i++){
    if (!idx[i].empty() || !idy[i].empty()){
      vector<pair<long long, int>> P;
      for (int j = 0; j <= N - i; j++){
        long long hash = (sum[j] - sum[j + i] * POW[i] % MOD + MOD) % MOD;
        P.push_back(make_pair(hash, j));
      }
      sort(P.begin(), P.end());
      for (int j : idx[i]){
        auto itr = lower_bound(P.begin(), P.end(), make_pair(hash1[j], -1));
        if (itr == P.end()){
          ok[j] = false;
        } else if ((*itr).first != hash1[j]){
          ok[j] = false;
        } else {
          l[j] = (*itr).second;
        }
      }
      for (int j : idy[i]){
        auto itr = upper_bound(P.begin(), P.end(), make_pair(hash2[j], N));
        if (itr == P.begin()){
          ok[j] = false;
        } else {
          itr--;
          if ((*itr).first != hash2[j]){
            ok[j] = false;
          } else {
            r[j] = (*itr).second + y[j].size();
          }
        }
      }
    }
  }
  for (int i = 0; i < m; i++){
    if (!ok[i]){
      cout << 0 << endl;
    } else if (r[i] - l[i] < (int) max(x[i].size(), y[i].size())){
      cout << 0 << endl;
    } else {
      cout << r[i] - l[i] << endl;
    }
  }
}
accuracy: 0.925
time_ms: 1250
memory_kb: 33848
final_rank: 20

code_snippet: #include <bits/stdc++.h>
using namespace std;
const long long BASE = 1000000;
const long long MOD = 1000000007;
int main(){
  string S;
  cin >> S;
  int m;
  cin >> m;
  vector<string> x(m), y(m);
  for (int i = 0; i < m; i++){
    cin >> x[i] >> y[i];
  }
  int N = S.size();
  vector<long long> POW(N + 1);
  POW[0] = 1;
  for (int i = 0; i < N; i++){
    POW[i + 1] = POW[i] * BASE % MOD;
  }
  vector<long long> sum(N + 1);
  sum[N] = 0;
  for (int i = N - 1; i >= 0; i--){
    sum[i] = (sum[i + 1] * BASE + S[i]) % MOD;
  }
  vector<long long> hash1(m, 0), hash2(m, 0);
  for (int i = 0; i < m; i++){
    int sz1 = x[i].size();
    for (int j = 0; j < sz1; j++){
      hash1[i] += x[i][j] * POW[j];
      hash1[i] %= MOD;
    }
    int sz2 = y[i].size();
    for (int j = 0; j < sz2; j++){
      hash2[i] += y[i][j] * POW[j];
      hash2[i] %= MOD;
    }
  }
  vector<bool> ok(m, true);
  vector<vector<int>> idx(N + 1);
  vector<vector<int>> idy(N + 1);
  for (int i = 0; i < m; i++){
    if (x[i].size() <= N){
      idx[x[i].size()].push_back(i);
    } else {
      ok[i] = false;
    }
    if (y[i].size() <= N){
      idy[y[i].size()].push_back(i);
    } else {
      ok[i] = false;
    }
  }
  vector<int> l(m), r(m);
  for (int i = 1; i <= N; i++){
    if (!idx[i].empty() || !idy[i].empty()){
      vector<pair<long long, int>> P;
      for (int j = 0; j <= N - i; j++){
        long long hash = (sum[j] - sum[j + i] * POW[i] % MOD + MOD) % MOD;
        P.push_back(make_pair(hash, j));
      }
      sort(P.begin(), P.end());
      for (int j : idx[i]){
        auto itr = lower_bound(P.begin(), P.end(), make_pair(hash1[j], -1));
        if (itr == P.end()){
          ok[j] = false;
        } else if ((*itr).first != hash1[j]){
          ok[j] = false;
        } else {
          l[j] = (*itr).second;
        }
      }
      for (int j : idy[i]){
        auto itr = upper_bound(P.begin(), P.end(), make_pair(hash2[j], N));
        if (itr == P.begin()){
          ok[j] = false;
        } else {
          itr--;
          if ((*itr).first != hash2[j]){
            ok[j] = false;
          } else {
            r[j] = (*itr).second + y[j].size();
          }
        }
      }
    }
  }
  for (int i = 0; i < m; i++){
    if (!ok[i]){
      cout << 0 << endl;
    } else if (r[i] - l[i] < (int) max(x[i].size(), y[i].size())){
      cout << 0 << endl;
    } else {
      cout << r[i] - l[i] << endl;
    }
  }
}
accuracy: 0.975
time_ms: 1230
memory_kb: 33848
final_rank: 19

code_snippet: #include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 1000000007;
const ll INF = mod * mod;
typedef pair<int, int>P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-12;
const ld pi = acosl(-1.0);

ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	ll n;
	modint() :n(0) { ; }
	modint(ll m) :n(m) {
		if (n >= mod)n %= mod;
		else if (n < 0)n = (n % mod + mod) % mod;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 18;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}

struct SegT {
private:
	int sz; vector<int> node;
	const int init_c = mod;
public:
	SegT(vector<int> v) {
		int n = v.size();
		sz = 1;
		while (sz < n)sz *= 2;
		node.resize(2 * sz - 1, init_c);
		rep(i, n) {
			node[i + sz - 1] = v[i];
		}
		per(i, sz - 1) {
			node[i] = f(node[2 * i + 1], node[2 * i + 2]);
		}
	}
	SegT(int n) {
		sz = 1;
		while (sz < n)sz *= 2;
		node.resize(2 * sz - 1, init_c);
	}
	int f(int a, int b) {
		return min(a, b);
	}
	void update(int k, int a) {
		k += sz - 1;
		node[k] = a;
		while (k > 0) {
			k = (k - 1) / 2;
			node[k] = f(node[k * 2 + 1], node[k * 2 + 2]);
		}
	}
	int query(int a, int b, int k = 0, int l = 0, int r = -1) {
		if (r < 0)r = sz;
		if (r <= a || b <= l)return init_c;
		else if (a <= l && r <= b)return node[k];
		else {
			int vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
			int vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
			return f(vl, vr);
		}
	}
};


struct SuffixArray {
	struct SAComp {
		const int h;
		const vector<int>& g;
		SAComp(int h, vector<int>& g) : h(h), g(g) { ; }
		bool operator() (int a, int b) {
			return a != b && (g[a] != g[b] ? g[a] < g[b] : g[a + h] < g[b + h]);
		}
	};
	int n;
	string str;
	vector<int> sa, lcp;
	SuffixArray(const string& t) : n(t.size()), sa(n + 1), lcp(n + 1) {
		str = t;
		// build SA
		vector<int> g(n + 1, 0), b(n + 1, 0);
		rep(i, n + 1) { sa[i] = i; g[i] = str[i]; }
		sort(begin(sa), end(sa), SAComp(0, g));
		for (int h = 1; b[n] != n; h *= 2) {
			SAComp comp(h, g);
			sort(sa.begin(), sa.end(), comp);
			rep(i, n) b[i + 1] = b[i] + comp(sa[i], sa[i + 1]);
			rep(i, n + 1) g[sa[i]] = b[i];
		}
		// build LCP
		int h = 0;
		rep(i, n + 1) b[sa[i]] = i;
		rep(i, n + 1) {
			if (b[i]) {
				for (int j = sa[b[i] - 1]; j + h < n && i + h < n && str[j + h] == str[i + h]; ++h);
				lcp[b[i]] = h;
			}
			else {
				lcp[b[i]] = -1;
			}
			if (h > 0) --h;
		}
	}
	~SuffixArray() { str.clear(); }
	/*int find(string t) {
	int m = t.size();
	string p;
	p = t;
	int left = -1, right = n + 1;
	while (left + 1 < right) {
	int mid = (left + right) / 2;
	if (strncmp(str + sa[mid], p, m) < 0) left = mid;
	else right = mid;
	}
	return strncmp(str + sa[right], p, m) == 0 ? sa[right] : -1;
	}*/
};

void solve() {
	string s; cin >> s;
	int m; cin >> m;
	vector<string> a(m), b(m);
	rep(i, m)cin >> a[i] >> b[i];
	string rs = s; reverse(all(rs));
	SuffixArray sa(s), rsa(rs);
	auto find_nex = [&](vector<int>& sa, string& s, int dep, int l, int r, char c)->P {
		if (l >= r)return { l,r };
		P res;
		int le = l - 1, ri = r;
		while (ri - le > 1) {
			int mid = (le + ri) / 2;
			if (dep + sa[mid] >= s.size()) {
				le = mid;
			}
			else {
				if (s[sa[mid] + dep] < c) {
					le = mid;
				}
				else {
					ri = mid;
				}
			}
		}
		res.first = ri;
		le = l - 1, ri = r;
		while (ri - le > 1) {
			int mid = (le + ri) / 2;
			if (dep + sa[mid] >= s.size()) {
				le = mid;
			}
			if (s[sa[mid] + dep] > c)ri = mid;
			else le = mid;
		}
		res.second = ri;
		return res;
	};
	SegT st(sa.sa);
	SegT rst(rsa.sa);
	rep(i, m) {
		P p = { 0,s.size() + 1 };
		rep(j, a[i].size()) {
			p = find_nex(sa.sa, s, j, p.first, p.second, a[i][j]);
		}
		if (p.first >= p.second) {
			cout << 0 << "\n"; continue;
		}
		int l = st.query(p.first, p.second);
		p = { 0,rs.size() + 1 };
		reverse(all(b[i]));
		rep(j, b[i].size()) {
			p = find_nex(rsa.sa, rs, j, p.first, p.second, b[i][j]);
		}
		if (p.first >= p.second) {
			cout << 0 << "\n"; continue;
		}
		int r = rst.query(p.first, p.second);
		r = s.size() - 1 - r;
		int len = r - l + 1;
		if (len < 0)len = 0;
		if (len < a[i].size() || len < b[i].size()) {
			cout << 0 << "\n";
		}
		else {
			cout << len << "\n";
		}
	}
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	//cout << fixed << setprecision(10);
	//init_f();
	//init();
	//expr();
	//int t; cin >> t;rep(i,t)
	//while(cin>>n>>t>>k,n)
	solve();
	return 0;
}
accuracy: 1
time_ms: 260
memory_kb: 22264
final_rank: 6

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define REP(i, n) for (int i=0; i<(n); ++i)
#define RREP(i, n) for (int i=(int)(n)-1; i>=0; --i)
#define FOR(i, a, n) for (int i=(a); i<(n); ++i)
#define RFOR(i, a, n) for (int i=(int)(n)-1; i>=(a); --i)

#define SZ(x) ((int)(x).size())
#define ALL(x) (x).begin(),(x).end()

#define DUMP(x) cerr<<#x<<" = "<<(x)<<endl
#define DEBUG(x) cerr<<#x<<" = "<<(x)<<" (L"<<__LINE__<<")"<<endl;

template<class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  os << "[";
  REP(i, SZ(v)) {
    if (i) os << ", ";
    os << v[i];
  }
  return os << "]";
}

template<class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  return os << "(" << p.first << " " << p.second << ")";
}

template<class T>
bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

template<class T>
bool chmin(T &a, const T &b) {
  if (b < a) {
    a = b;
    return true;
  }
  return false;
}

using ll = long long;
using ull = unsigned long long;
using ld = long double;
using P = pair<int, int>;
using vi = vector<int>;
using vll = vector<ll>;
using vvi = vector<vi>;
using vvll = vector<vll>;

const ll MOD = 1e9 + 7;
const int INF = INT_MAX / 2;
const ll LINF = LLONG_MAX / 2;
const ld eps = 1e-9;

/**
 * @brief Trie
 * @author habara-k
 * @tparam char_size 文字の種類数. ASCIIで連続していること.
 * @tparam margin 0番目の文字 (e.g. 'a')
 * @usage
 * AhoCorasick PMA(26,'a');
 * PMA.add("pattern");
 * int now = root;
 * string s;
 * for (char c : s) {
 *     while (PMA.nodes[now].nxt[c - 'a'] == -1) {
 *         now = PMA.nodes[now].nxt[FAIL];
 *     }
 *     now = PMA.nodes[now].nxt[c - 'a'];
 *     // nowはsをcまで読んだときのノード.
 *     // ここでPMA.nodes[now].acceptとかを利用していろいろやる
 * }
 */
template<int char_size, int margin>
struct AhoCorasick {
  const int root = 0, FAIL = char_size;
  /**
   * 構築後の各メンバの値
   * nxt[FAIL]:
   *   次の文字に対応する遷移先がない場合,
   *   nxt[FAIL]に移動してから次の文字に遷移する
   * accept[id]:
   *   今見てる文字でちょうどマッチしたパターンのidをカウントしたmap
   */
  struct Node {
    vector<int> nxt;
    map<int,int> accept;
    Node() : nxt(char_size + 1, -1) {}
  };
  vector<Node> nodes = {Node()};

  /**
   * @brief パターンの追加 O(|s|)
   * @param s 追加するパターン
   * @param id パターンのid. sの終端に対応するノードのacceptに追加される.
   */
  void add(const string& s, int id = 0) {
    int now = root;
    for (char c : s) {
      if (nodes[now].nxt[c - margin] == -1) {
        nodes[now].nxt[c - margin] = nodes.size();
        nodes.push_back(Node());
      }
      now = nodes[now].nxt[c - margin];
    }
    ++nodes[now].accept[id];
  }

  /**
   * @brief PMAの構築.
   */
  void build() {
    queue<int> que;
    for (int i = 0; i < char_size; ++i) {
      if (nodes[root].nxt[i] == -1) {
        nodes[root].nxt[i] = root;
      } else {
        que.push(nodes[root].nxt[i]);
        nodes[nodes[root].nxt[i]].nxt[FAIL] = root;
      }
    }
    while (!que.empty()) {
      int now = que.front(); que.pop();
      for (int i = 0; i < char_size; ++i) {
        if (nodes[now].nxt[i] == -1) continue;
        int fail = nodes[now].nxt[FAIL];
        while (nodes[fail].nxt[i] == -1) {
          fail = nodes[fail].nxt[FAIL];
        }
        nodes[nodes[now].nxt[i]].nxt[FAIL] = nodes[fail].nxt[i];
        for (const auto& tp : nodes[nodes[fail].nxt[i]].accept) {
          nodes[nodes[now].nxt[i]].accept[tp.first] += tp.second;
        }
        que.push(nodes[now].nxt[i]);
      }
    }
  }

  /**
   * @brief デバッグ
   * <node> ::= {id #:<fail先のid>, a:<(aの遷移先の)node>, ..., z:<(zの遷移先の)node>}
   */
  friend ostream& operator<<(ostream& os, const AhoCorasick& pma) {
    const int n = pma.nodes.size();
    vector<bool> used(n);
    function<void(int)> dfs = [&](int now) {
      used[now] = true;
      os << "{" << now << " " << "#:" << pma.nodes[now].nxt[pma.FAIL];
      for (int i = 0; i < char_size; ++i) {
        int nxt = pma.nodes[now].nxt[i];
        if (nxt != -1) {
          os << ", " << (char)(i + margin) << ":";
          if (!used[nxt]) dfs(nxt);
          else os << nxt;
        }
      }
      os << "}";
    };
    dfs(pma.root);
    return os;
  }
};

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(10);

  string s; cin >> s;
  int m; cin >> m;
  using PSS = pair<string, string>;
  vector<PSS> queries(m);
  set<string> st;
  map<string, int> mp;
  REP(i, m) {
    cin >> queries[i].first >> queries[i].second;
    st.insert(queries[i].first);
    st.insert(queries[i].second);
  }

  int id = 0;
  for(auto &e: st) {
    mp[e] = id;
    id++;
  }

  map<int, vector<P>> to_query;
  REP(i, m) {
    to_query[mp[queries[i].first]].emplace_back(i, 0);
    to_query[mp[queries[i].second]].emplace_back(i, 1);
  }

  AhoCorasick<26, 'a'> aho;
  for(auto &e: st) {
    aho.add(e, mp[e]);
  }

  aho.build();

  vector<int> vmi(id, INF);
  vector<int> vma(id, -INF);

  vector<P> v(m);
  REP(i, m) {
    v[i].first = INF;
    v[i].second = -INF;
  }
  int now = aho.root;
  const int FAIL = 26;
  REP(i, SZ(s)) {
    char c = s[i];
    //cout << i << ":" << c << endl;
    while(aho.nodes[now].nxt[c - 'a'] == -1) {
      now = aho.nodes[now].nxt[FAIL];
    }
    now = aho.nodes[now].nxt[c - 'a'];

    for(auto &e: aho.nodes[now].accept) {
      if(e.second == 0) continue;

      chmin(vmi[e.first], i);
      chmax(vma[e.first], i);

      /*
      for(auto &e2: to_query[e.first]) {
        int idx, tmp;
        tie(idx, tmp) = e2;
        if(tmp == 0) {
          chmin(v[idx].first, i);
        } else {
          chmax(v[idx].second, i);
        }
      }
       */
    }
  }

  REP(i, id) {
    for(auto &e: to_query[i]) {
      int idx, tmp;
      tie(idx, tmp) = e;
      if(tmp == 0) {
        chmin(v[idx].first, vmi[i]);
      } else {
        chmax(v[idx].second, vma[i]);
      }
    }
  }


  REP(i, m) {
    //cout << v[i].second << " " << v[i].first << " " << SZ(queries[i].second) << " " << SZ(queries[i].first) << endl;
    //if(v[i].second - v[i].first < SZ(queries[i].second) - SZ(queries[i].first)) {
    if(v[i].second < v[i].first || v[i].first == INF || v[i].second == -INF) {
      cout << 0 << endl;
    } else {
      int len = v[i].second - v[i].first + SZ(queries[i].first);
      cout << max(0, len) << endl;
    }
  }

  return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 42684
final_rank: 9