Problem:
Problem D. Prefix Suffix Search
As an English learner, sometimes you cannot remember the entire spelling of English words perfectly, but you can only remember their prefixes and suffixes. For example, you may want to use a word which begins with '
appr
' and ends with '
iate
', but forget the middle part of the word. It may be '
appreciate
', '
appropriate
', or something like them.
By using an ordinary dictionary, you can look up words beginning with a certain prefix, but it is inconvenient for further filtering words ending with a certain suffix. Thus it is helpful to achieve dictionary functionality which can be used for finding words with a given prefix and suffix. In the beginning, let's count the number of such words instead of explicitly listing them.
More formally, you are given a list of $N$ words. Next, you are given $Q$ queries consisting of two strings. Your task is to write a program which outputs the number of words with the prefix and suffix for each query in the given list.
Input
The input consists of a single test case in the following format.
$N$ $Q$
$w_1$
$...$
$w_N$
$p_1$ $s_1$
$...$
$p_Q$ $s_Q$
The first line contains two integers $N$ and $Q$, where $N$ ($1 \leq N \leq 10^5$) is the number of words in the list, and $Q$ ($1 \leq Q \leq 10^5$) is the number of queries. The $i$-th line of the following $N$ lines contains a string $w_i$. The $i$-th of the following $Q$ lines contains two strings $p_i$ and $s_i$, which are a prefix and suffix of words to be searched, respectively.
You can assume the followings:
All the strings in an input are non-empty and consist only of lowercase English letters.
The total length of input strings does not exceed $2,500,000$.
Words in the given list are unique: $w_i \ne w_j$ if $i \ne j$.
Pairs of a prefix and suffix are unique: $(p_i, s_i) \ne (p_j, s_j)$ if $i \ne j$.
Output
For each query, output the number of words with a given prefix and suffix in the given list per a line.
Examples
Sample Input 1
6 7
appreciate
appropriate
acceptance
ace
acm
acetylene
appr iate
a e
a a
ac ce
ace e
acceptance acceptance
no match
Output for Sample Input 1
2
5
0
2
2
1
0
Sample Input 2
5 5
d
dd
ddd
dddd
ddddd
d d
dd dd
ddd ddd
d dddd
ddddd dd
Output for Sample Input 2
5
4
3
2
1
Sample Input 3
7 4
connected
disconnected
graph
directed
diameter
distance
minor
c ed
di ed
dis ed
dis e
Output for Sample Input 3
1
2
1
1

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
 
#pragma GCC optimize("O2")
using namespace std;
#define ll long long
#define ull unsigned long long
#define rep(i,n,N) for(ll i=n;i<=N;++i)
#define rap(i,n,N) for(ll i=n;i>=N;--i)
#define mp make_pair
#define pb push_back
#define pob pop_back
#define pf push_front
#define pof pop_front
#define fi first
#define se second
//#define ff fi.fi
//#define fs fi.se
//#define sf se.fi
//#define ss se.se
#define lc (id<<1)
#define rc ((id<<1)|1)
#define db(x) cerr << ">>>>>> " << #x << " -> " << x << endl
#define nani(x) cerr <<  "Line " << __LINE__ << ": " << #x << " is " << x << endl
#define all(x) x.begin(),x.end()
#define pii pair<int,int> 
#define pll pair<ll,ll>
#define plll pair<ll,pll>
#define piii pair<int,pii>
#define piiii pair<pii,pii>
#define psi pair<string,int>
#define endl '\n'
const int MAX = 1e5+5;
const ll MAX2 = 11;
const ll MOD = 1000000007;
const ll MOD2 = 1000005329;
const ll INF = 2e18;
const int dr[]={1,0,-1,0,1,1,-1,-1,0};
const int dc[]={0,1,0,-1,1,-1,1,-1,0};
const double pi = acos(-1);
const double EPS = 1e-9;
const int block = 2000;

int n,q,ans[MAX],bit[MAX],le,ri,mid,a,b,ret,sz;
psi x[MAX];
string pr[MAX],sf[MAX];
pii res[MAX];
vector<int> kur[MAX],tam[MAX];

inline int cmp(string &a,string &b){
	sz = min(a.size(),b.size())-1;
	rep(i,0,sz){
		if(a[i]<b[i])return 1;
		if(a[i]>b[i])return -1;
	}
	return a.size()<b.size();
}

inline void f(string &s){
	le = 1, ri = n, a = 0;
	while(le<=ri){
		mid = le+ri>>1;
		ret = cmp(x[mid].fi,s);
		if(ret==1)le = mid+1;
		else if(ret==-1)ri = mid-1;
		else a = mid, ri = mid-1;
	}
	if(!a)return;
	le = 1, ri = n, b = 0;
	while(le<=ri){
		mid = le+ri>>1;
		ret = cmp(x[mid].fi,s);
		if(ret==1)le = mid+1;
		else if(ret==-1)ri = mid-1;
		else b = mid, le = mid+1;
	}
	return;
}

inline void upd(int i){
	for(; i<=n; i+=(i&-i))++bit[i];
	return;
}

inline int que(int i){
	ret = 0;
	for(; i>0; i-=(i&-i))ret+=bit[i];
	return ret;
}

int main(){
//	cout<<fixed<<setprecision(2);
//    freopen("input.txt", "r", stdin);
//	freopen("output.txt","w",stdout);
    ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    cin>>n>>q;
    rep(i,1,n)cin>>x[i].fi;
    sort(x+1,x+1+n);
//    cout<<"___________\n";
//    rep(i,1,n)cout<<x[i].fi<<endl;
    rep(i,1,q){
    	cin>>pr[i]>>sf[i];
    	f(pr[i]);
    	res[i] = {a-1,b};
//    	cout<<a<<' '<<b<<endl;
	}
	rep(i,1,n)reverse(all(x[i].fi)), x[i].se = i;
    sort(x+1,x+1+n);
//    cout<<"___________\n";
//    rep(i,1,n)cout<<x[i].fi<<endl;
    rep(i,1,q){
    	if(res[i].fi==-1)continue;
    	reverse(all(sf[i]));
    	f(sf[i]);
    	if(!a)continue;
//    	cout<<a<<' '<<b<<endl;
    	kur[a-1].pb(i);
    	tam[b].pb(i);
	}
	rep(i,1,n){
		upd(x[i].se);
		for(auto j:kur[i])ans[j]-= que(res[j].se) - que(res[j].fi);
		for(auto j:tam[i])ans[j]+= que(res[j].se) - que(res[j].fi);
	}
	rep(i,1,q)cout<<ans[i]<<endl;
    return 0;
}
accuracy: 1
time_ms: 120
memory_kb: 25824
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define si(a) (long)a.size()
#define fi first
#define se second
#define all(x) x.begin(),x.end()
#define rep(i,n) for(long i=0;i<(long)(n);++i)
template<typename T>bool chmin(T&a,T b){return b<a?(a=b,1):0;}
template<typename T>bool chmax(T&a,T b){return b>a?(a=b,1):0;}
struct _ {
   _() { cin.tie(0)->sync_with_stdio(0), cout.tie(0), cout << fixed << setprecision(16); }
} __;

template<class S> struct merge_sort_tree {
    int n;
    vector<vector<S>> d, s;
    merge_sort_tree(vector<S>& a): n(__bit_ceil(si(a))), d(n * 2), s(n * 2) {
        rep(i, si(a)) d[n + i] = {a[i]};
        for(int i = n; --i;) {
            merge(all(d[i * 2]), all(d[i * 2 + 1]), back_inserter(d[i]));
        }
    }
    int range_cnt(int l, int r, S& u) {
        int ret = 0;
        for(l += n, r += n; l < r; l >>= 1, r >>= 1) {
            if(l & 1) ret += lower_bound(all(d[l]), u) - d[l].begin(), l++;
            if(r & 1) --r, ret += lower_bound(all(d[r]), u) - d[r].begin();
        }
        return ret;
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int N, Q;
    cin >> N >> Q;
    vector<string> S(N);
    rep(i, N) cin >> S[i];
    sort(all(S));
    vector<string> T = S;
    rep(i, N) reverse(all(T[i]));
    merge_sort_tree<string> tree(T);
    rep(i, Q) {
        string p, s;
        cin >> p >> s;
        int l = lower_bound(all(S), p) - S.begin();
        p += "|";
        int r = lower_bound(all(S), p) - S.begin();
        reverse(all(s));
        int ans = 0;
        ans -= tree.range_cnt(l, r, s);
        s += '|';
        ans += tree.range_cnt(l, r, s);
        cout << ans << "\n";
    }
}
accuracy: 1
time_ms: 390
memory_kb: 147208
final_rank: 11

code_snippet: ////////////////////////////////////////////
///                                      ///
///         Template ver. 1 rapel        ///
/// Fear is Temporary, Regret is Forever ///
///          Must Try and Get AC         ///
///                                      ///
////////////////////////////////////////////
#include <stdio.h>
#include <iostream>
#include <sstream>
#include <iomanip>

#include <algorithm>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <utility>

#include <math.h>
#include <complex>

#include <assert.h>
#include <time.h>
//#include <chrono>
//#include <random>

#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <list>
#include <bitset>

#define FI first
#define SE second
#define MP make_pair
#define PB push_back
#define PF push_front
#define POB pop_back
#define POF pop_front
#define endl '\n'
using namespace std;

typedef long long LL;
typedef unsigned long long ULL;

void desperate_optimization(int precision){
  	ios_base::sync_with_stdio(false);
  	cin.tie(0);
  	cout.tie(0);
  	cout.setf(ios::fixed);
  	cout.setf(ios::showpoint);
  	cout.precision(precision);
}

const int N = 1e5;
vector<string> vec;
vector<pair<string,int> > rev;

struct node{
	node *left, *right;
	int total;
};

node *head[N + 5];

node *update(node *curr, node *pre, int l,int r,int tar) {
	curr = new node();
	curr->total = pre->total + 1;
	curr->left = pre->left, curr->right = pre->right;
	if(l == r) return curr;
	int mid = (l + r) / 2;
	if(tar <= mid) curr->left = update(curr->left, pre->left, l, mid, tar);
	else curr->right = update(curr->right, pre->right, mid + 1, r, tar);
	return curr;
}

int query(node *curr, node *pre, int l,int r,int le,int ri) {
	if(r < le || ri < l) return 0;
	if(le <= l && r <= ri) return curr->total - pre->total;
	int mid = (l + r) / 2;
	return query(curr->left, pre->left, l, mid, le, ri) + query(curr->right, pre->right, mid + 1,r, le, ri);
}

void hora(int tc) {
	int n,m;
	cin>>n>>m;
	for(int i = 1;i <= n;i++) {
		string s;
		cin>>s;
		vec.PB(s);
	}
	sort(vec.begin(), vec.end());
	for(int i = 0;i < n;i++) {
		string s = vec[i];
		reverse(s.begin(), s.end());
		rev.PB({s, i});
	}
	sort(rev.begin(), rev.end());
	head[0] = new node();
	head[0]->left = head[0]->right = head[0];
	head[0]->total = 0;
	for(int i = 0;i < n;i++) {
		head[i + 1] = update(head[i + 1], head[i], 0, n - 1, rev[i].SE);
	}
	while(m--) {
		string pre,suf;
		cin>>pre>>suf;
		reverse(suf.begin(), suf.end());
		int lo = 0;
		int hi = n - 1;
		int lhs = -1;
		int rhs = n;
		while(lo <= hi) {
			int mid = (lo + hi) / 2;
			if(vec[mid] < pre) {
				lo = mid + 1;
				lhs = mid;
			} else hi = mid - 1;
		}
		lo = 0;
		hi = n - 1;
		pre += '{';
		while(lo <= hi) {
			int mid = (lo + hi) / 2;
			if(vec[mid] > pre) {
				hi = mid - 1;
				rhs = mid;
			} else lo = mid + 1;
		}
		lhs++, rhs--;
		if(lhs > rhs) {
			cout<<0<<endl;
			continue;
		}
		if(lhs <= rhs) {
			int lo = 0;
			int hi = n - 1;
			int l = -1;
			int r = n;
			while(lo <= hi) {
				int mid = (lo + hi) / 2;
				if(rev[mid].FI < suf) {
					lo = mid + 1;
					l = mid;
				} else hi = mid - 1;
			}
			lo = 0;
			hi = n - 1;
			suf += '{';
			while(lo <= hi) {
				int mid = (lo + hi) / 2;
				if(rev[mid].FI > suf) {
					hi = mid - 1;
					r = mid;
				} else lo = mid + 1;
			}
			l++, r--;
			if(l > r) {
				cout<<0<<endl;
				continue;
			} else {
				cout<<query(head[r + 1], head[l], 0, n - 1, lhs, rhs)<<endl;
			}
		}
	}
}

int main(){
	desperate_optimization(10);
	int ntc = 1;
	//cin>>ntc;
	for(int tc = 1;tc <= ntc;tc++) hora(tc);
	return 0;
}
accuracy: 1
time_ms: 240
memory_kb: 73200
final_rank: 10

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

using namespace std;

int main() {
    int n, q; cin >> n >> q;
    vector<string> words(n);
    for(int i = 0; i < n; i++) cin >> words[i];
    n = bit_ceil((unsigned)n);
    words.resize(n, "~");
    ranges::sort(words);
    vector<vector<string>> seg(n+n);
    for(int i = 0; i < n; i++) seg[n+i].push_back(string(words[i].rbegin(), words[i].rend()));
    for(int i = n-1; i >= 1; i--) {
        seg[i].reserve(ssize(seg[i*2]) + ssize(seg[i*2+1]));
        ranges::merge(seg[i*2], seg[i*2+1], back_inserter(seg[i]));
    }
    while(q--) {
        string pre, suf; cin >> pre >> suf;
        ranges::reverse(suf);
        int l = ranges::lower_bound(words, pre) - words.begin();
        int r = ranges::lower_bound(words, pre + "~") - words.begin();
        l += n, r += n;
        int ans = 0;
        while(l < r) {
            if(l & 1) {
                ans += ranges::lower_bound(seg[l], suf + "~") - ranges::lower_bound(seg[l], suf);
                l++;
            }
            if(r & 1) {
                --r;
                ans += ranges::lower_bound(seg[r], suf + "~") - ranges::lower_bound(seg[r], suf);
            }
            l >>= 1;
            r >>= 1;
        }
        cout << ans << '\n';
    }
}
accuracy: 1
time_ms: 540
memory_kb: 153492
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define all(v) (v).begin(),(v).end()
#define pb(a) push_back(a)
#define rep(i, n) for(int i=0;i<n;i++)
#define foa(e, v) for(auto&& e : v)
using ll = long long;
const ll MOD7 = 1000000007, MOD998 = 998244353, INF = (1LL << 60);
#define dout(a) cout<<fixed<<setprecision(10)<<a<<endl;

template <class T> struct BIT {
    int n;
    vector<T> a;
    BIT(int m) : n(m), a(m + 1, 0) {}
    void add(int x, T y) {
        x ++;
        while(x <= n) {
            a[x] += y;
            x += x & -x;
        }
    }
    T sum(int x) {
        T r = 0;
        while(x > 0) {
            r += a[x];
            x -= x & -x;
        }
        return r;
    }
    T sum(int x, int y) {
        return sum(y) - sum(x);
    }
};

int lb(vector<string> &s, string &t) {
    int n = s.size();
    int len = t.size();
    int le = -1, ri = n;
    while(ri - le > 1) {
        int mid = (ri + le) >> 1;
        // t <= s -> ri = mid
        int l = s[mid].size();
        int ll = min(l, len);
        int f = 0;
        rep(i, ll) {
            if(s[mid][i] == t[i]) continue;
            if(s[mid][i] < t[i]) f = 1;
            else f = -1;
            break;
        }
        if((f == -1) or (f == 0 and len <= l)) {
            ri = mid;
        } else {
            le = mid;
        }
    }
    return ri;
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int n, q;
    cin >> n >> q;
    vector<string> s(n), rev(n);
    vector<int> apply(n, -1);
    rep(i, n) {
        cin >> s[i];
        rev[i] = s[i];
        reverse(all(rev[i]));
    }
    sort(all(s));
    sort(all(rev));
    vector<int> v(n);

    rep(i, n) {
        auto S = s[i];
        reverse(all(S));
        // int id = find(all(rev), S) - rev.begin();
        v[i] = lb(rev, S);
    }
    vector<int> ans(q, 0);
    vector<vector<tuple<int, int, int, int>>> query(n);
    rep(i, q) {
        string a, b;
        cin >> a >> b;
        reverse(all(b));
        {
            // int x1 = lower_bound(all(s), a) - s.begin();
            int x1 = lb(s, a);
            a += "~";
            int x2 = lb(s, a);
            // int x2 = lower_bound(all(s), a) - s.begin();
            // int y1 = lower_bound(all(rev), b) - rev.begin();
            int y1 = lb(rev, b);
            b += "~";
            int y2 = lb(rev, b);
            // int y2 = lower_bound(all(rev), b) - rev.begin();
            if(x2 == 0) continue;
            if(x1 == 0) query[x2 - 1].push_back({y1, y2, i, 1});
            else {
                query[x2 - 1].push_back({y1, y2, i, 1});
                query[x1 - 1].push_back({y1, y2, i, -1});
            }
        }
    }
    BIT<int> bit(n);
    rep(i, n) {
        bit.add(v[i], 1);
        for(auto [y1, y2, id, k] : query[i]) {
            ans[id] += k * bit.sum(y1, y2); 
        }
    }
    foa(e, ans) cout << e << endl;
    return 0;
}
accuracy: 1
time_ms: 240
memory_kb: 27460
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define all(v) (v).begin(),(v).end()
#define pb(a) push_back(a)
#define rep(i, n) for(int i=0;i<n;i++)
#define foa(e, v) for(auto&& e : v)
using ll = long long;
const ll MOD7 = 1000000007, MOD998 = 998244353, INF = (1LL << 60);
#define dout(a) cout<<fixed<<setprecision(10)<<a<<endl;

template <class T> struct BIT {
    int n;
    vector<T> a;
    BIT(int m) : n(m), a(m + 1, 0) {}
    void add(int x, T y) {
        x ++;
        while(x <= n) {
            a[x] += y;
            x += x & -x;
        }
    }
    T sum(int x) {
        T r = 0;
        while(x > 0) {
            r += a[x];
            x -= x & -x;
        }
        return r;
    }
    T sum(int x, int y) {
        return sum(y) - sum(x);
    }
};

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int n, q;
    cin >> n >> q;
    vector<string> s(n), rev(n);
    vector<int> apply(n, -1);
    rep(i, n) {
        cin >> s[i];
        rev[i] = s[i];
        reverse(all(rev[i]));
    }
    sort(all(s));
    sort(all(rev));
    vector<int> v(n);
    rep(i, n) {
        auto S = s[i];
        reverse(all(S));
        int id = find(all(rev), S) - rev.begin();
        v[i] = id;
    }
    vector<int> ans(q, 0);
    vector<vector<tuple<int, int, int, int>>> query(n);
    rep(i, q) {
        string a, b;
        cin >> a >> b;
        reverse(all(b));
        {
            int x1 = lower_bound(all(s), a) - s.begin();
            a += "~";
            int x2 = lower_bound(all(s), a) - s.begin();
            int y1 = lower_bound(all(rev), b) - rev.begin();
            b += "~";
            int y2 = lower_bound(all(rev), b) - rev.begin();
            if(x1 == 0) query[x2 - 1].push_back({y1, y2, i, 1});
            else {
                query[x2 - 1].push_back({y1, y2, i, 1});
                query[x1 - 1].push_back({y1, y2, i, -1});
            }
        }
    }
    BIT<int> bit(n);
    rep(i, n) {
        if(v[i] == n) {
            return 0;
        }
        bit.add(v[i], 1);
        for(auto [y1, y2, id, k] : query[i]) {
            ans[id] += k * bit.sum(y1, y2); 
        }
    }
    foa(e, ans) cout << e << endl;
    return 0;
}
accuracy: 0.3333333333333333
time_ms: 100
memory_kb: 9008
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define all(v) (v).begin(),(v).end()
#define pb(a) push_back(a)
#define rep(i, n) for(int i=0;i<n;i++)
#define foa(e, v) for(auto&& e : v)
using ll = long long;
const ll MOD7 = 1000000007, MOD998 = 998244353, INF = (1LL << 60);
#define dout(a) cout<<fixed<<setprecision(10)<<a<<endl;

template <class T> struct BIT {
    int n;
    vector<T> a;
    BIT(int m) : n(m), a(m + 1, 0) {}
    void add(int x, T y) {
        x ++;
        while(x <= n) {
            a[x] += y;
            x += x & -x;
        }
    }
    T sum(int x) {
        T r = 0;
        while(x > 0) {
            r += a[x];
            x -= x & -x;
        }
        return r;
    }
    T sum(int x, int y) {
        return sum(y) - sum(x);
    }
};

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int n, q;
    cin >> n >> q;
    vector<string> s(n), rev(n);
    vector<int> apply(n, -1);
    rep(i, n) {
        cin >> s[i];
        rev[i] = s[i];
        reverse(all(rev[i]));
    }
    sort(all(s));
    sort(all(rev));
    vector<int> v(n);
    rep(i, n) {
        auto S = s[i];
        reverse(all(S));
        int id = find(all(rev), S) - rev.begin();
        v[i] = id;
    }
    vector<int> ans(q, 0);
    vector<vector<tuple<int, int, int, int>>> query(n);
    rep(i, q) {
        string a, b;
        cin >> a >> b;
        reverse(all(b));
        {
            int x1 = lower_bound(all(s), a) - s.begin();
            a += "~";
            int x2 = lower_bound(all(s), a) - s.begin();
            int y1 = lower_bound(all(rev), b) - rev.begin();
            b += "~";
            int y2 = lower_bound(all(rev), b) - rev.begin();
            if(x1 == 0) query[x2 - 1].push_back({y1, y2, i, 1});
            else {
                query[x2 - 1].push_back({y1, y2, i, 1});
                query[x1 - 1].push_back({y1, y2, i, -1});
            }
        }
    }
    BIT<int> bit(n);
    rep(i, n) {
        bit.add(v[i], 1);
        for(auto [y1, y2, id, k] : query[i]) {
            if(y1 < 0 or y2 > n or y1 > y2) {
                return 0;
            }
            ans[id] += k * bit.sum(y1, y2); 
        }
    }
    foa(e, ans) cout << e << endl;
    return 0;
}
accuracy: 0.3333333333333333
time_ms: 100
memory_kb: 9048
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define all(v) (v).begin(),(v).end()
#define pb(a) push_back(a)
#define rep(i, n) for(int i=0;i<n;i++)
#define foa(e, v) for(auto&& e : v)
using ll = long long;
const ll MOD7 = 1000000007, MOD998 = 998244353, INF = (1LL << 60);
#define dout(a) cout<<fixed<<setprecision(10)<<a<<endl;

template <class T> struct BIT {
    int n;
    vector<T> a;
    BIT(int m) : n(m), a(m + 1, 0) {}
    void add(int x, T y) {
        x ++;
        while(x <= n) {
            a[x] += y;
            x += x & -x;
        }
    }
    T sum(int x) {
        T r = 0;
        while(x > 0) {
            r += a[x];
            x -= x & -x;
        }
        return r;
    }
    T sum(int x, int y) {
        return sum(y) - sum(x);
    }
};

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int n, q;
    cin >> n >> q;
    vector<string> s(n), rev(n);
    vector<int> apply(n, -1);
    rep(i, n) {
        cin >> s[i];
        rev[i] = s[i];
        reverse(all(rev[i]));
    }
    sort(all(s));
    sort(all(rev));
    vector<int> v(n);
    rep(i, n) {
        auto S = s[i];
        reverse(all(S));
        int id = find(all(rev), S) - rev.begin();
        v[i] = id;
    }
    vector<int> ans(q, 0);
    vector<vector<tuple<int, int, int, int>>> query(n);
    rep(i, q) {
        string a, b;
        cin >> a >> b;
        reverse(all(b));
        {
            int x1 = lower_bound(all(s), a) - s.begin();
            a += "~";
            int x2 = lower_bound(all(s), a) - s.begin();
            int y1 = lower_bound(all(rev), b) - rev.begin();
            b += "~";
            int y2 = lower_bound(all(rev), b) - rev.begin();
            if(x1 == 0) query[x2 - 1].push_back({y1, y2, i, 1});
            else {
                query[x2 - 1].push_back({y1, y2, i, 1});
                query[x1 - 1].push_back({y1, y2, i, -1});
            }
        }
    }
    BIT<int> bit(n);
    rep(i, n) {
        bit.add(v[i], 1);
        for(auto [y1, y2, id, k] : query[i]) {
            // cout <<i << " " << y1 << " " << y2 << " " << id << " " << k << endl;
            ans[id] += k * bit.sum(y1, y2); 
        }
    }
    foa(e, ans) cout << e << endl;
    return 0;
}
accuracy: 0.3333333333333333
time_ms: 100
memory_kb: 8956
final_rank: 17

code_snippet: #include <iostream>
#include <string>
#include <vector>
#include <utility>
#include <cassert>
#include <algorithm>
struct SegmentTree {
    int n;
    std::vector<std::vector<int>> data;
    SegmentTree(std::vector<int> A) : n{(int)A.size()}, data(2 * n) {
        for (int i{} ; i < n ; i++) data[n + i] = {A[i]};
        for (int i{n - 1} ; i >= 1 ; i--) {
            for (int x : data[i << 1 | 0]) data[i].push_back(x);
            for (int x : data[i << 1 | 1]) data[i].push_back(x);
            std::sort(data[i].begin(), data[i].end());
        }
    }
    int prod(int l, int r, int d, int u) const {
        assert(0 <= l and l <= r and r <= n);
        assert(d <= u);
        int L{}, R{};
        for (l += n, r += n ; l < r ; l >>= 1, r >>= 1) {
            if (l & 1) {
                L += std::lower_bound(data[l].begin(), data[l].end(), u) - std::lower_bound(data[l].begin(), data[l].end(), d);
                l++;
            }
            if (r & 1) {
                r--;
                R += std::lower_bound(data[r].begin(), data[r].end(), u) - std::lower_bound(data[r].begin(), data[r].end(), d);
            }
        }
        return L + R;
    }
};
int N, Q;
std::string W[100010], P[100010], S[100010];
bool prefix(const std::string& s, const std::string& p) {
    return p.size() <= s.size() and s.substr(0, p.size()) == p;
}
void solve() {
    std::vector<std::pair<std::string, int>> A(N), B(N);
    for (int i{} ; i < N ; i++) {
        A[i] = B[i] = {W[i], i};
        std::reverse(B[i].first.begin(), B[i].first.end());
    }
    std::sort(A.begin(), A.end());
    std::sort(B.begin(), B.end());
    std::vector<int> L(Q), R(Q), D(Q), U(Q);
    for (int i{} ; i < Q ; i++) std::reverse(S[i].begin(), S[i].end());
    for (int i{} ; i < Q ; i++) {
        L[i] = std::lower_bound(A.begin(), A.end(), std::pair{P[i], -1}) - A.begin();
        D[i] = std::lower_bound(B.begin(), B.end(), std::pair{S[i], -1}) - B.begin();
    }
    for (int i{} ; i < Q ; i++) {
        if (L[i] == N or !prefix(A[L[i]].first, P[i])) R[i] = L[i];
        else {
            int ok{L[i]}, ng{N};
            while (ng - ok > 1) {
                int mid{(ok + ng) / 2};
                (prefix(A[mid].first, P[i]) ? ok : ng) = mid;
            }
            R[i] = ng;
        }
        if (D[i] == N or !prefix(B[D[i]].first, S[i])) U[i] = D[i];
        else {
            int ok{D[i]}, ng{N};
            while (ng - ok > 1) {
                int mid{(ok + ng) / 2};
                (prefix(B[mid].first, S[i]) ? ok : ng) = mid;
            }
            U[i] = ng;
        }
    }
    std::vector<std::pair<int, int>> XY(N);
    for (int i{} ; i < N ; i++) {
        XY[A[i].second].first = i;
        XY[B[i].second].second = i;
    }
    std::vector<int> init(N);
    for (const auto [x, y] : XY) {
        init[x] = y;
    }
    // for (int i{} ; i < N ; i++) std::cout << init[i] << ' ';
    // std::cout << std::endl;
    SegmentTree seg{init};
    for (int i{} ; i < Q ; i++) {
        // std::cout << L[i] << ' ' << R[i] << ' ' << D[i] << ' ' << U[i] << std::endl;
        std::cout << seg.prod(L[i], R[i], D[i], U[i]) << '\n';
    }
}
int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);
    std::cin >> N >> Q;
    for (int i{} ; i < N ; i++) {
        std::cin >> W[i];
    }
    for (int i{} ; i < Q ; i++) {
        std::cin >> P[i] >> S[i];
    }
    solve();
}
accuracy: 1
time_ms: 290
memory_kb: 52588
final_rank: 9

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 BIT{
    int n; T all=0; vector<T> val;
    BIT(int _n=0):n(_n),val(_n+10){}
    void clear(){val.assign(n+10,0); all=T();}
    void add(int i,T x){
        for(i++;i<=n;i+=(i&-i))val[i]=val[i]+x;
        all+=x;
    }
    T sum(int i){
        T res=0;
        for(;i;i-=(i&-i))res+=val[i];
        return res;
    }
    T sum(int L,int R){return sum(R)-sum(L);} // [L,R)

    int lower_bound(T x){
        int ret=0,len=1;
        while(2*len<=n)len<<=1;
        for(;len>=1;len>>=1){
            if(ret+len<=n and val[ret+len]<x){
                ret+=len;
                x-=val[ret];
            }
        }
        return ret;
    }
};

/**
 * @brief Binary Indexed Tree
 */

struct Query {
    int XL, XR, YL, YR;
};

int main() {
    int N, Q;
    cin >> N >> Q;
    vector<pair<string,int>> S(N), T(N);
    rep(i,0,N) {
        cin >> S[i].first;
        S[i].second = i;
        T[i] = S[i];
        reverse(ALL(T[i].first));
    }
    sort(ALL(S)), sort(ALL(T));
    vector<pair<int,int>> P(N);
    rep(i,0,N) {
        P[S[i].second].first = i;
        P[T[i].second].second = i;
    }
    vector<Query> A(Q);
    rep(i,0,Q) {
        string Pre, Suf;
        cin >> Pre >> Suf;
        reverse(ALL(Suf));
        pair<string,int> PSI;
        PSI = {Pre,-1};
        A[i].XL = LB(S,PSI);
        Pre += (char)('z'+1);
        PSI = {Pre,-1};
        A[i].XR = UB(S,PSI);
        PSI = {Suf,-1};
        A[i].YL = LB(T,PSI);
        Suf += (char)('z'+1);
        PSI = {Suf,-1};
        A[i].YR = UB(T,PSI);
    }
    vector<int> Add(N);
    rep(i,0,N) Add[P[i].first] = P[i].second;
    vector<vector<pair<int,int>>> QID(N+1);
    rep(i,0,Q) {
        QID[A[i].XL].push_back({i,0});
        QID[A[i].XR].push_back({i,1});
    }
    vector<int> ANS(Q);
    BIT<ll> Seg(N);
    rep(i,0,N+1) {
        for (auto ID : QID[i]) {
            if (ID.second == 0) {
                ANS[ID.first] -= Seg.sum(A[ID.first].YL, A[ID.first].YR);
            }
            else {
                ANS[ID.first] += Seg.sum(A[ID.first].YL, A[ID.first].YR);
            }
        }
        if (i != N) {
            Seg.add(Add[i],1);
        }
    }
    rep(i,0,Q) cout << ANS[i] << endl;
}
accuracy: 1
time_ms: 240
memory_kb: 29408
final_rank: 6

code_snippet: #include"bits/stdc++.h"
//#include"atcoder/all"
using namespace std;
//using namespace atcoder;
#pragma GCC target("avx2")
#pragma GCC optimize("O2")
#pragma GCC optimize("unroll-loops")
using ll = long long;
using ld = long double;
#define rep(i,m,n) for(ll i=(ll)m;i<(ll)n;i++)
#define drep(i,m,n) for(ll i=m-1;i>=n;i--)
#define Endl endl
#define pr(i,j) make_pair(i,j) 
#define isin(x,l,r) (l<=x&&x<r)
#define chmin(a,b) a=min(a,b)
#define chmax(a,b) a=max(a,b)
#define srt(ar) sort(ar.begin(),ar.end())
#define rev(ar) reverse(ar.begin(),ar.end())
#define jge(f) cout<<(f?"Yes":"No")<<endl
const ll inf = 1e18;
const ld pi = 3.14159265358979;
const ld eps = 1e-9;
//using mint = modint1000000007;
clock_t ST, FN;

////////////////////////////////////////////////marge_sort_tree
template<class T> size_t HashCombine(const size_t seed, const T& v) {
    return seed ^ (std::hash<T>()(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2));
}
template<class T, class S> struct std::hash<std::pair<T, S>> {
    size_t operator()(const std::pair<T, S>& keyval) const noexcept {
        return HashCombine(std::hash<T>()(keyval.first), keyval.second);
    }
};
template<typename T=long long> 
class marge_sort_tree {
private:
    unordered_map<pair<ll, ll>, vector<T>>mp;
    //unordered_map<pair<ll, ll>, vector<T>>mp_s;
    vector<T>ar;
    ll sz_ar;
    T INF;
    void init_mp(ll l, ll r) {
        vector<T>in;
        //vector<ll>in_s(1);
        rep(i, l, r)in.push_back(ar[i]);
        sort(in.begin(), in.end());
        //rep(i, 0, r - l)in_s.push_back(in_s.back() + in[i]);
        mp[make_pair(l, r)] = in;
       // mp_s[make_pair(l, r)] = in_s;
        if (r - l > 1) {
            init_mp(l, (l + r) / 2);
            init_mp((l + r) / 2, r);
        }
    }
    ll cnt_call(ll l, ll r, ll L, ll R, T x) {
        if (l <= L && R <= r) {
            auto itr = lower_bound(mp[make_pair(L, R)].begin(), mp[make_pair(L, R)].end(), x);
            return distance(mp[make_pair(L, R)].begin(), itr);
        }
        else if (r <= L || R <= l)return 0;
        else return cnt_call(l, r, L, (L + R) / 2, x) + cnt_call(l, r, (L + R) / 2, R, x);
    }
    /*ll sum_call(ll l, ll r, ll L, ll R, T x) {
        if (l <= L && R <= r) {
            auto itr = lower_bound(mp[make_pair(L, R)].begin(), mp[make_pair(L, R)].end(), x);
            return mp_s[make_pair(L, R)][distance(mp[make_pair(L, R)].begin(), itr)];
        }
        else if (r <= L || R <= l)return 0;
        else return sum_call(l, r, L, (L + R) / 2, x) + sum_call(l, r, (L + R) / 2, R, x);
    }*/
public:
    marge_sort_tree(vector<T>init,T INF_init) {
        sz_ar = 1;
        while (init.size() > sz_ar)sz_ar *= 2;
        ar.resize(sz_ar, INF_init);
        rep(i, 0, init.size()) {
            ar[i] = init[i];
        }
        init_mp(0, sz_ar);
    }
    //[l,r)においてx未満のものの個数を返す O((logn)^2)
    ll cnt(ll l, ll r, T x) {
        return cnt_call(l, r, 0LL, sz_ar, x);
    }
    //[l,r)においてx未満のものの総和を返す O((logn)^2)
    /*
    ll sum(ll l, ll r, T x) {
        return sum_call(l, r, 0LL, sz_ar, x);
    }*/
};
//////////////////////////////////////////////////ここまで
int main() {
	ST = clock();
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	ll n, q;
	cin >> n >> q;
	vector<string>s(n);
	rep(i, 0, n)cin >> s[i];
	srt(s);
	//rep(i, 0, n)cout << s[i] << endl;
	vector<string>sr = s;
	rep(i, 0, n) {
		rev(sr[i]);
	}
	string INF = "z";
	INF[0] += 1;
	marge_sort_tree<string>mt(sr,INF);
	rep(i, 0, q) {
		ll ans = 0;
		string Pre, Suf;
		cin >> Pre >> Suf;
		string Prf = Pre;
		Prf.back() += (char)1;
		rev(Suf);
		ll L = distance(s.begin(),lower_bound(s.begin(), s.end(), Pre));
		ll R = distance(s.begin(), lower_bound(s.begin(), s.end(), Prf));
		//cout << L << " " << R << endl;
		string Sug = Suf;
		Sug.back() += (char)1;
		ans += mt.cnt(L, R, Sug) - mt.cnt(L, R, Suf);
		cout << ans << endl;
	}
}
accuracy: 1
time_ms: 1160
memory_kb: 198856
final_rank: 14

code_snippet: // competitive-verifier: PROBLEM
#ifdef ATCODER
#pragma GCC target("sse4.2,avx512f,avx512dq,avx512ifma,avx512cd,avx512bw,avx512vl,bmi2")
#endif
#pragma GCC optimize("Ofast,fast-math,unroll-all-loops")
#include <bits/stdc++.h>
#ifndef ATCODER
#pragma GCC target("sse4.2,avx2,bmi2")
#endif
template <class T, class U>
constexpr bool chmax(T &a, const U &b) {
    return a < (T)b ? a = (T)b, true : false;
}
template <class T, class U>
constexpr bool chmin(T &a, const U &b) {
    return (T)b < a ? a = (T)b, true : false;
}
constexpr std::int64_t INF = 1000000000000000003;
constexpr int Inf = 1000000003;
constexpr double EPS = 1e-7;
constexpr double PI = 3.14159265358979323846;
#define FOR(i, m, n) for (int i = (m); i < int(n); ++i)
#define FORR(i, m, n) for (int i = (m)-1; i >= int(n); --i)
#define FORL(i, m, n) for (int64_t i = (m); i < int64_t(n); ++i)
#define rep(i, n) FOR (i, 0, n)
#define repn(i, n) FOR (i, 1, n + 1)
#define repr(i, n) FORR (i, n, 0)
#define repnr(i, n) FORR (i, n + 1, 1)
#define all(s) (s).begin(), (s).end()
struct Sonic {
    Sonic() {
        std::ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
        std::cout << std::fixed << std::setprecision(20);
    }
    constexpr void operator()() const {}
} sonic;
using namespace std;
using ll = std::int64_t;
using ld = long double;
template <class T, class U>
std::istream &operator>>(std::istream &is, std::pair<T, U> &p) {
    return is >> p.first >> p.second;
}
template <class T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
    for (T &i : v) is >> i;
    return is;
}
template <class T, class U>
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &p) {
    return os << '(' << p.first << ',' << p.second << ')';
}
template <class T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &v) {
    for (auto it = v.begin(); it != v.end(); ++it) os << (it == v.begin() ? "" : " ") << *it;
    return os;
}
template <class Head, class... Tail>
void co(Head &&head, Tail &&...tail) {
    if constexpr (sizeof...(tail) == 0) std::cout << head << '\n';
    else std::cout << head << ' ', co(std::forward<Tail>(tail)...);
}
template <class Head, class... Tail>
void ce(Head &&head, Tail &&...tail) {
    if constexpr (sizeof...(tail) == 0) std::cerr << head << '\n';
    else std::cerr << head << ' ', ce(std::forward<Tail>(tail)...);
}
void Yes(bool is_correct = true) { std::cout << (is_correct ? "Yes\n" : "No\n"); }
void No(bool is_not_correct = true) { Yes(!is_not_correct); }
void YES(bool is_correct = true) { std::cout << (is_correct ? "YES\n" : "NO\n"); }
void NO(bool is_not_correct = true) { YES(!is_not_correct); }
void Takahashi(bool is_correct = true) { std::cout << (is_correct ? "Takahashi" : "Aoki") << '\n'; }
void Aoki(bool is_not_correct = true) { Takahashi(!is_not_correct); }
namespace internal {
/**
 * @brief 完備辞書
 *
 * @see https://ei1333.github.io/library/structure/wavelet/succinct-indexable-dictionary.hpp
 */
struct bit_vector {
    bit_vector() = default;
    bit_vector(unsigned int _length)
        : length(_length), blocks((_length + 31) >> 5), bit((_length + 31) >> 5),
          sum((_length + 31) >> 5) {}
    void set(unsigned int k) { bit[k >> 5] |= 1U << (k & 31); }
    void build() {
        sum[0] = 0U;
        for (unsigned int i = 1; i < blocks; ++i) {
            sum[i] = sum[i - 1] + __builtin_popcount(bit[i - 1]);
        }
    }
    bool operator[](unsigned int k) const { return bit[k >> 5] >> (k & 31) & 1; }
    unsigned int rank(unsigned int k) const {
        return sum[k >> 5] + __builtin_popcount(bit[k >> 5] & ((1U << (k & 31)) - 1));
    }
    unsigned int rank(bool val, unsigned int k) const { return val ? rank(k) : k - rank(k); }
    unsigned int select(unsigned int k) const {
        unsigned int sl = 0, sr = blocks + 1;
        while (sr - sl > 1) {
            unsigned int m = (sl + sr) >> 1;
            if (sum[m] < k) sl = m;
            else sr = m;
        }
        k -= sum[sl];
        unsigned int bl = 0, br = 32;
        while (br - bl > 1) {
            unsigned int m = (bl + br) >> 1;
            if (__builtin_popcount(bit[sl] & ((1U << m) - 1)) < k) bl = m;
            else br = m;
        }
        return (sl << 5) + bl;
    }
  private:
    unsigned int length, blocks;
    std::vector<unsigned int> bit, sum;
};
}  // namespace internal
/**
 * @brief ウェーブレット行列
 * @see https://ei1333.github.io/library/structure/wavelet/wavelet-matrix.hpp
 *
 * @tparam T
 * @tparam L
 */
template <class T, int L = 20>
struct wavelet_matrix {
    wavelet_matrix() = default;
    wavelet_matrix(std::vector<T> v) : length(v.size()) {
        std::vector<T> l(length), r(length);
        for (int level = L - 1; level >= 0; --level) {
            matrix[level] = internal::bit_vector(length + 1);
            int left = 0, right = 0;
            for (int i = 0; i < length; ++i) {
                if (v[i] >> level & 1) {
                    matrix[level].set(i);
                    r[right++] = v[i];
                } else {
                    l[left++] = v[i];
                }
            }
            mid[level] = left;
            matrix[level].build();
            v.swap(l);
            for (int i = 0; i < right; ++i) v[left + i] = r[i];
        }
    }
    T access(int k) const {
        T res = 0;
        for (int level = L - 1; level >= 0; --level) {
            bool f = matrix[level][k];
            if (f) res |= T(1) << level;
            k = matrix[level].rank(f, k) + mid[level] * f;
        }
        return res;
    }
    T operator[](int k) const { return access(k); }
    /// count i s.t. (0 <= i < r) && v[i] == x
    int rank(int r, T x) const {
        int l = 0;
        for (int level = L - 1; level >= 0; --level) {
            std::tie(l, r) = succ((x >> level) & 1, l, r, level);
        }
        return r - l;
    }
    /// count i s.t. (l <= i < r) && v[i] == x
    int rank(int l, int r, T x) const { return rank(r, x) - rank(l, x); }
    /// k-th smallest number in v[l ... r-1]
    T kth_smallest(int l, int r, int k) const {
        assert(0 <= k && k < r - l);
        T res = 0;
        for (int level = L - 1; level >= 0; --level) {
            int cnt = matrix[level].rank(false, r) - matrix[level].rank(false, l);
            bool f = cnt <= k;
            if (f) {
                res |= T(1) << level;
                k -= cnt;
            }
            std::tie(l, r) = succ(f, l, r, level);
        }
        return res;
    }
    /// k-th largest number in v[l ... r-1]
    T kth_largest(int l, int r, int k) const { return kth_smallest(l, r, r - l - k - 1); }
    /// count i s.t. (l <= i < r) && (v[i] < upper)
    int range_freq(int l, int r, T upper) const {
        int res = 0;
        for (int level = L - 1; level >= 0; --level) {
            bool f = ((upper >> level) & 1);
            if (f) res += matrix[level].rank(false, r) - matrix[level].rank(false, l);
            std::tie(l, r) = succ(f, l, r, level);
        }
        return res;
    }
    /// count i s.t. (l <= i < r) && (lower <= v[i] < upper)
    int range_freq(int l, int r, T lower, T upper) const {
        return range_freq(l, r, upper) - range_freq(l, r, lower);
    }
    /// max v[i] s.t. (l <= i < r) && (v[i] < upper)
    T prev_value(int l, int r, T upper) const {
        int cnt = range_freq(l, r, upper);
        return cnt == 0 ? T(-1) : kth_smallest(l, r, cnt - 1);
    }
    /// min v[i] s.t. (l <= i < r) && (lower <= v[i])
    T next_value(int l, int r, T lower) const {
        int cnt = range_freq(l, r, lower);
        return cnt == r - l ? T(-1) : kth_smallest(l, r, cnt);
    }
  private:
    int length;
    internal::bit_vector matrix[L];
    int mid[L];
    std::pair<int, int> succ(bool f, int l, int r, int level) const {
        return {matrix[level].rank(f, l) + mid[level] * f,
                matrix[level].rank(f, r) + mid[level] * f};
    }
};
int main(void)
{
    int n, q;
    cin >> n >> q;
    vector<string> w(n);
    cin >> w;
    sort(all(w));
    vector<string> v = w;
    for (auto &s : v)
        reverse(all(s));
    vector<int> ord(n);
    iota(all(ord), 0);
    sort(all(ord), [&](int x, int y)
         { return v[x] < v[y]; });
    sort(all(v));
    vector<int> u(n);
    rep(i, n) u[ord[i]] = i;
    wavelet_matrix wm(u);
    while (q--)
    {
        string p, s;
        cin >> p >> s;
        reverse(all(s));
        int l = lower_bound(all(w), p) - w.begin();
        p += '~';
        int r = lower_bound(all(w), p) - w.begin();
        int x = lower_bound(all(v), s) - v.begin();
        s += '~';
        int y = lower_bound(all(v), s) - v.begin();
        co(wm.range_freq(l, r, x, y));
    }
    return 0;
}
accuracy: 1
time_ms: 170
memory_kb: 19656
final_rank: 2

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

int inf = 1001001001;

template <typename T>
struct SegmentTree {
    int n;
    vector<T> dat;
    SegmentTree() {}
    SegmentTree(int N) {
        n = 1;
        while(n < N) {
            n *= 2;
        }
        dat.resize(2*n-1,inf);
    }
    void update(int x, T val) {
        x += n-1;
        dat[x] = val;
        while(x > 0) {
            x = (x-1)/2;
            dat[x] = min(dat[2*x+1],dat[2*x+2]);
        }
    }
    T query(int a, int b, int k, int l, int r) {
        if(r <= a || b <= l) return inf;
        if(a <= l && r <= b) return dat[k];
        T vl = query(a, b, 2*k+1, l, (l+r)/2);
        T vr = query(a, b, 2*k+2, (l+r)/2, r);
        return min(vl, vr);
    }
    T query(int a,int b) {//[a,b)
        return query(a,b,0,0,n);
    }
};

/*
 Luzhiled Library
 */
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 T > // 一つ前とその文字列
vector< int > lcp_array(const SuffixArray< T > &sa) {
    int n = (int) sa.size() - 1;
    vector< int > lcp(n + 1), rank(n + 1);
    for(int i = 0; i <= n; i++) {
        rank[sa[i]] = i;
    }
    int h = 0;
    for(int i = 0; i <= n; i++) {
        if(rank[i] < n) {
            int j = sa[rank[i] + 1];
            for(; j + h < n && i + h < n; h++) {
                if(sa.vs[j + h] != sa.vs[i + h]) break;
            }
            lcp[rank[i] + 1] = h;
            if(h > 0) h--;
        }
    }
    return lcp;
}

template <typename T>
struct BinaryIndexedTree {
    int N;
    vector<T>bit;
    BinaryIndexedTree(){}
    BinaryIndexedTree(int x) {
        N = x;
        bit.resize(x+1);
    }
    void add(int x,T y) {
        while(x <= N) {
            bit[x] += y;
            x += x&-x;
        }
    }
    T sum(int x) {
        T res = 0;
        while(x) {
            res += bit[x];
            x -= x&-x;
        }
        return res;
    }
    inline T sum(int l, int r) {//[l,r]
        return sum(r)-sum(l-1);
    }
    inline T operator[](int k) {
        return sum(k)-sum(k-1);
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int N,Q;
    cin >> N >> Q;
    vector<string>w(N);
    for(int i = 0; i < N; i++) {
        cin >> w[i];
    }
    vector<string>p(Q),s(Q);
    for(int i = 0; i < Q; i++) {
        cin >> p[i] >> s[i];
    }
    string S = "",T = "";
    vector<int>id1(N),id2(N);
    for(int i = 0; i < N; i++) {
        id1[i] = S.size();
        id2[i] = T.size();
        S += w[i]+'$';
        reverse(w[i].begin(),w[i].end());
        T += w[i]+'$';
    }
    vector<int>Id1(Q),Id2(Q);
    for(int i = 0; i < Q; i++) {
        Id1[i] = S.size();
        Id2[i] = T.size();
        S += p[i];
        reverse(s[i].begin(),s[i].end());
        T += s[i];
    }
    SuffixArray sa1(S),sa2(T);
    vector<int> lcp1 = lcp_array(sa1) , lcp2 = lcp_array(sa2);
    sa1.erase(sa1.begin());
    sa2.erase(sa2.begin());
    lcp1.erase(lcp1.begin());
    lcp2.erase(lcp2.begin());
    vector<int>f1(S.size()),f2(T.size());
    SegmentTree<int> Seg1(S.size()),Seg2(T.size());
    for(int i = 0; i < sa1.size(); i++) {
        f1[sa1[i]] = i;
        Seg1.update(i,lcp1[i]);
    }
    for(int i = 0; i < sa2.size(); i++) {
        f2[sa2[i]] = i;
        Seg2.update(i,lcp2[i]);
    }
    priority_queue<array<int,4>,vector<array<int,4>>,greater<array<int,4>>>que;
    for(int i = 0; i < N; i++) {
        que.push({f1[id1[i]],0,f2[id2[i]],-1});
    }
    vector<int>ans(Q);
    for(int i = 0; i < Q; i++) {
        int x = f1[Id1[i]],y = f2[Id2[i]];
        int l1 = -1,r1 = S.size(),l2 = -1,r2 = T.size();
        {
            int r = x;
            while(l1+1 < r) {
                int mid = (l1+r)/2;
                if(Seg1.query(mid+1,x+1) < p[i].size()) {
                    l1 = mid;
                }
                else {
                    r = mid;
                }
            }
            l1 = r;
        }
        {
            int l = x;
            while(l+1 < r1) {
                int mid = (l+r1)/2;
                if(Seg1.query(x+1,mid+1) < p[i].size()) {
                    r1 = mid;
                }
                else {
                    l = mid;
                }
            }
            r1 = l;
        }
        {
            int r = y+1;
            while(l2+1 < r) {
                int mid = (l2+r)/2;
                if(Seg2.query(mid+1,y+1) < s[i].size()) {
                    l2 = mid;
                }
                else {
                    r = mid;
                }
            }
            l2 = r;
        }
        {
            int l = y;
            while(l+1 < r2) {
                int mid = (l+r2)/2;
                if(Seg2.query(y+1,mid+1) < s[i].size()) {
                    r2 = mid;
                }
                else {
                    l = mid;
                }
            }
            r2 = l;
        }
        que.push({l1-1,i*2+1,l2,r2});
        que.push({r1,i*2+2,l2,r2});
    }
    BinaryIndexedTree<int>bit(T.size());
    while(!que.empty()) {
        array<int,4> ar = que.top();
        que.pop();
        if(ar[1] == 0) {
            bit.add(ar[2]+1,1);
        }
        else if(ar[1]%2 == 1) {
            ans[ar[1]/2] -= bit.sum(ar[2]+1,ar[3]+1);
        }
        else if(ar[1]%2 == 0) {
            ans[ar[1]/2-1] += bit.sum(ar[2]+1,ar[3]+1);
        }
    }
    for(int i = 0; i < Q; i++) {
        cout << ans[i] << "\n";
    }
}
accuracy: 1
time_ms: 1750
memory_kb: 152904
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vi = vector<int>;
using pii = pair<int, int>;
#define rep(i, x)    for(int i = 0; i < (x); i++)
#define rng(i, l, r) for(int i = (l); i < (r); i++)
#define all(v)       (v).begin(), (v).end()
#define sz(v)        (int)(v).size()

struct fenwick_tree {
	vector<ll> s;
	fenwick_tree(int n) : s(n) {}
	void add(int pos, ll c = 1) {
		for(; pos < sz(s); pos |= pos + 1) s[pos] += c;
	}
	ll query(int pos) {
		ll res = 0;
		for(; pos > 0; pos &= pos - 1) res += s[pos - 1];
		return res;
	}
	ll query(int l, int r) { return query(r) - query(l); }
};

int main() {
	int n, q;
	cin >> n >> q;
	vector<string> s(n);
	for(auto &v : s) cin >> v;
	sort(all(s));
	auto s_rev = s;
	for(auto &v : s_rev) reverse(all(v));
	vector<pair<string, int>> s_rev_id;
	rep(i, n) s_rev_id.emplace_back(s_rev[i], i);
	sort(all(s_rev_id));
	sort(all(s_rev));
	vector<int> pt(n);
	rep(i, n) {
		pt[s_rev_id[i].second] = i;
	}
	vector<int> lx(q), rx(q), ly(q), ry(q);
	vector<vector<pii>> jobs(n + 1);
	rep(i, q) {
		string a, b;
		cin >> a >> b;
		reverse(all(b));
		char x = 'z' + 1;
		lx[i] = lower_bound(all(s), a) - s.begin();
		rx[i] = lower_bound(all(s), a + x) - s.begin();
		ly[i] = lower_bound(all(s_rev), b) - s_rev.begin();
		ry[i] = lower_bound(all(s_rev), b + x) - s_rev.begin();
		jobs[lx[i]].emplace_back(ly[i], ry[i]);
		jobs[rx[i]].emplace_back(ly[i], ry[i]);
	}
	fenwick_tree bt(n);
	using T = tuple<int, int, int>;
	map<T, int> mp;
	rep(i, n + 1) {
		for(auto [ly, ry] : jobs[i]) {
			mp[T{i, ly, ry}] = bt.query(ly, ry);
		}
		if(i < n) bt.add(pt[i]);
	}
	rep(i, q) {
		cout << mp[T{rx[i], ly[i], ry[i]}] - mp[T{lx[i], ly[i], ry[i]}] << endl;
	}
}
accuracy: 1
time_ms: 310
memory_kb: 39136
final_rank: 8

code_snippet: #define DEBUG(...)
/*                        Strip me down and go to town                        */
/*                          Lick me over upside down                          */
/*                     Pound and pound and pound and pound                    */
/*                        Baby make me make that sound                        */
/*                Aaah, aaah, aaah, aaah, aaaaaaaaaaaaaaaaaah!                */
#include<iostream>
#include<stdio.h>
#include<string>
#include<algorithm>
#include<vector>
using namespace std;

vector<string> dict;

namespace TRIE {
  struct node {
    int cnt;
    node *nxt[26];
  };
  node *newNode() {
    node *ret = (node*)malloc(sizeof(node));
    ret->cnt = 0;
    for (int i = 0; i < 26; i++) ret->nxt[i] = NULL;
    return ret;
  }
  node *add(node *last, string &str) {
    node *ret = newNode();
    node *cur = ret;
    if (last) cur->cnt = last->cnt + 1;
    else cur->cnt = 1;
    for (int i = str.length()-1; i >= -1; i--) {
      if (last) {
        for (int j = 0; j < 26; j++) {
          cur->nxt[j] = last->nxt[j];
        }
      }
      if (i == -1) break;
      cur->nxt[str[i] - 'a'] = newNode();
      cur = cur->nxt[str[i] - 'a'];
      if (last) last = last->nxt[str[i] - 'a'];
      if (last) cur->cnt = last->cnt + 1;
      else cur->cnt = 1;
    }
    return ret;
  }
  int chk(node *ver, string &str) {
    node *cur = ver;
    for (int i = str.length()-1; i >= 0 && cur != NULL; i--) {
      cur = cur->nxt[str[i] - 'a'];
    }
    if (cur) return cur->cnt;
    return 0;
  }
}
TRIE::node *ver[100005];
int substr(string &S, string &s) {
  if (s.length() > S.length()) return 0;
  for (int i = 0; i < s.length(); i++) {
    if (S[i] != s[i]) return 0;
  }
  return 1;
}

int main() {
  int n, q;
  scanf("%d %d", &n, &q);
  for (int i = 0; i < n; i++) {
    string x;
    cin >> x;
    dict.push_back(x);
  }
  sort(dict.begin(), dict.end());
  ver[0] = NULL;
  for (int i = 0; i < n; i++) {
    ver[i+1] = TRIE::add(ver[i], dict[i]);
  }
  while (q--) {
    string pre, suf;
    cin >> pre >> suf;
    int L = n, R = -1;
    int l = 0, r = n-1;
    while (l <= r) {
      int mid = (l + r) / 2;
      int val = substr(dict[mid], pre);
      if (dict[mid] > pre || val) {
        if (val) L = mid;
        r = mid - 1;
      } else {
        l = mid + 1;
      }
    }
    l = 0, r = n-1;
    while (l <= r) {
      int mid = (l + r) / 2;
      int val = substr(dict[mid], pre);
      if (dict[mid] < pre || val) {
        if (val) R = mid;
        l = mid + 1;
      } else {
        r = mid - 1;
      }
    }
    int ans = 0;
    if (L <= R) {
      ans = TRIE::chk(ver[R+1], suf) - TRIE::chk(ver[L], suf);
    }
    printf("%d\n", ans);
  }
  return 0;
}
accuracy: 1
time_ms: 480
memory_kb: 428004
final_rank: 15

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

#ifdef _MSC_VER
#  include <intrin.h>
#else
#  include <x86intrin.h>
#endif

#include <limits>
#include <type_traits>

namespace suisen {
// ! utility
template <typename ...Types>
using constraints_t = std::enable_if_t<std::conjunction_v<Types...>, std::nullptr_t>;
template <bool cond_v, typename Then, typename OrElse>
constexpr decltype(auto) constexpr_if(Then&& then, OrElse&& or_else) {
    if constexpr (cond_v) {
        return std::forward<Then>(then);
    } else {
        return std::forward<OrElse>(or_else);
    }
}

// ! function
template <typename ReturnType, typename Callable, typename ...Args>
using is_same_as_invoke_result = std::is_same<std::invoke_result_t<Callable, Args...>, ReturnType>;
template <typename F, typename T>
using is_uni_op = is_same_as_invoke_result<T, F, T>;
template <typename F, typename T>
using is_bin_op = is_same_as_invoke_result<T, F, T, T>;

template <typename Comparator, typename T>
using is_comparator = std::is_same<std::invoke_result_t<Comparator, T, T>, bool>;

// ! integral
template <typename T, typename = constraints_t<std::is_integral<T>>>
constexpr int bit_num = std::numeric_limits<std::make_unsigned_t<T>>::digits;
template <typename T, unsigned int n>
struct is_nbit { static constexpr bool value = bit_num<T> == n; };
template <typename T, unsigned int n>
static constexpr bool is_nbit_v = is_nbit<T, n>::value;

// ?
template <typename T>
struct safely_multipliable {};
template <>
struct safely_multipliable<int> { using type = long long; };
template <>
struct safely_multipliable<long long> { using type = __int128_t; };
template <>
struct safely_multipliable<unsigned int> { using type = unsigned long long; };
template <>
struct safely_multipliable<unsigned long int> { using type = __uint128_t; };
template <>
struct safely_multipliable<unsigned long long> { using type = __uint128_t; };
template <>
struct safely_multipliable<float> { using type = float; };
template <>
struct safely_multipliable<double> { using type = double; };
template <>
struct safely_multipliable<long double> { using type = long double; };
template <typename T>
using safely_multipliable_t = typename safely_multipliable<T>::type;

template <typename T, typename = void>
struct rec_value_type {
    using type = T;
};
template <typename T>
struct rec_value_type<T, std::void_t<typename T::value_type>> {
    using type = typename rec_value_type<typename T::value_type>::type;
};
template <typename T>
using rec_value_type_t = typename rec_value_type<T>::type;

} // namespace suisen

// ! type aliases
using i128 = __int128_t;
using u128 = __uint128_t;

template <typename T>
using pq_greater = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <typename T, typename U>
using umap = std::unordered_map<T, U>;

// ! macros (capital: internal macro)
#define OVERLOAD2(_1,_2,name,...) name
#define OVERLOAD3(_1,_2,_3,name,...) name
#define OVERLOAD4(_1,_2,_3,_4,name,...) name

#define REP4(i,l,r,s)  for(std::remove_reference_t<std::remove_const_t<decltype(r)>>i=(l);i<(r);i+=(s))
#define REP3(i,l,r)    REP4(i,l,r,1)
#define REP2(i,n)      REP3(i,0,n)
#define REPINF3(i,l,s) for(std::remove_reference_t<std::remove_const_t<decltype(l)>>i=(l);;i+=(s))
#define REPINF2(i,l)   REPINF3(i,l,1)
#define REPINF1(i)     REPINF2(i,0)
#define RREP4(i,l,r,s) for(std::remove_reference_t<std::remove_const_t<decltype(r)>>i=(l)+fld((r)-(l)-1,s)*(s);i>=(l);i-=(s))
#define RREP3(i,l,r)   RREP4(i,l,r,1)
#define RREP2(i,n)     RREP3(i,0,n)

#define rep(...)    OVERLOAD4(__VA_ARGS__, REP4   , REP3   , REP2   )(__VA_ARGS__)
#define rrep(...)   OVERLOAD4(__VA_ARGS__, RREP4  , RREP3  , RREP2  )(__VA_ARGS__)
#define repinf(...) OVERLOAD3(__VA_ARGS__, REPINF3, REPINF2, REPINF1)(__VA_ARGS__)

#define CAT_I(a, b) a##b
#define CAT(a, b) CAT_I(a, b)
#define UNIQVAR(tag) CAT(tag, __LINE__)
#define loop(n) for (std::remove_reference_t<std::remove_const_t<decltype(n)>> UNIQVAR(loop_variable) = n; UNIQVAR(loop_variable) --> 0;)

#define all(iterable) std::begin(iterable), std::end(iterable)
#define input(type, ...) type __VA_ARGS__; read(__VA_ARGS__)

#ifdef LOCAL
#  define debug(...) debug_internal(#__VA_ARGS__, __VA_ARGS__)

template <class T, class... Args>
void debug_internal(const char* s, T&& first, Args&&... args) {
    constexpr const char* prefix = "[\033[32mDEBUG\033[m] ";
    constexpr const char* open_brakets = sizeof...(args) == 0 ? "" : "(";
    constexpr const char* close_brakets = sizeof...(args) == 0 ? "" : ")";
    std::cerr << prefix << open_brakets << s << close_brakets << ": " << open_brakets << std::forward<T>(first);
    ((std::cerr << ", " << std::forward<Args>(args)), ...);
    std::cerr << close_brakets << "\n";
}

#else
#  define debug(...) void(0)
#endif

// ! I/O utilities

// __int128_t
std::ostream& operator<<(std::ostream& dest, __int128_t value) {
    std::ostream::sentry s(dest);
    if (s) {
        __uint128_t tmp = value < 0 ? -value : value;
        char buffer[128];
        char* d = std::end(buffer);
        do {
            --d;
            *d = "0123456789"[tmp % 10];
            tmp /= 10;
        } while (tmp != 0);
        if (value < 0) {
            --d;
            *d = '-';
        }
        int len = std::end(buffer) - d;
        if (dest.rdbuf()->sputn(d, len) != len) {
            dest.setstate(std::ios_base::badbit);
        }
    }
    return dest;
}
// __uint128_t
std::ostream& operator<<(std::ostream& dest, __uint128_t value) {
    std::ostream::sentry s(dest);
    if (s) {
        char buffer[128];
        char* d = std::end(buffer);
        do {
            --d;
            *d = "0123456789"[value % 10];
            value /= 10;
        } while (value != 0);
        int len = std::end(buffer) - d;
        if (dest.rdbuf()->sputn(d, len) != len) {
            dest.setstate(std::ios_base::badbit);
        }
    }
    return dest;
}

// pair
template <typename T, typename U>
std::ostream& operator<<(std::ostream& out, const std::pair<T, U>& a) {
    return out << a.first << ' ' << a.second;
}
// tuple
template <unsigned int N = 0, typename ...Args>
std::ostream& operator<<(std::ostream& out, const std::tuple<Args...>& a) {
    if constexpr (N >= std::tuple_size_v<std::tuple<Args...>>) {
        return out;
    } else {
        out << std::get<N>(a);
        if constexpr (N + 1 < std::tuple_size_v<std::tuple<Args...>>) {
            out << ' ';
        }
        return operator<<<N + 1>(out, a);
    }
}
// vector
template <typename T>
std::ostream& operator<<(std::ostream& out, const std::vector<T>& a) {
    for (auto it = a.begin(); it != a.end();) {
        out << *it;
        if (++it != a.end()) out << ' ';
    }
    return out;
}
// array
template <typename T, size_t N>
std::ostream& operator<<(std::ostream& out, const std::array<T, N>& a) {
    for (auto it = a.begin(); it != a.end();) {
        out << *it;
        if (++it != a.end()) out << ' ';
    }
    return out;
}
inline void print() { std::cout << '\n'; }
template <typename Head, typename... Tail>
inline void print(const Head& head, const Tail &...tails) {
    std::cout << head;
    if (sizeof...(tails)) std::cout << ' ';
    print(tails...);
}
template <typename Iterable>
auto print_all(const Iterable& v, std::string sep = " ", std::string end = "\n") -> decltype(std::cout << *v.begin(), void()) {
    for (auto it = v.begin(); it != v.end();) {
        std::cout << *it;
        if (++it != v.end()) std::cout << sep;
    }
    std::cout << end;
}

__int128_t parse_i128(std::string& s) {
    __int128_t ret = 0;
    for (int i = 0; i < int(s.size()); i++) if ('0' <= s[i] and s[i] <= '9') ret = 10 * ret + s[i] - '0';
    if (s[0] == '-') ret = -ret;
    return ret;
}
__uint128_t parse_u128(std::string& s) {
    __uint128_t ret = 0;
    for (int i = 0; i < int(s.size()); i++) if ('0' <= s[i] and s[i] <= '9') ret = 10 * ret + s[i] - '0';
    return ret;
}
// __int128_t
std::istream& operator>>(std::istream& in, __int128_t& v) {
    std::string s;
    in >> s;
    v = parse_i128(s);
    return in;
}
// __uint128_t
std::istream& operator>>(std::istream& in, __uint128_t& v) {
    std::string s;
    in >> s;
    v = parse_u128(s);
    return in;
}
// pair
template <typename T, typename U>
std::istream& operator>>(std::istream& in, std::pair<T, U>& a) {
    return in >> a.first >> a.second;
}
// tuple
template <unsigned int N = 0, typename ...Args>
std::istream& operator>>(std::istream& in, std::tuple<Args...>& a) {
    if constexpr (N >= std::tuple_size_v<std::tuple<Args...>>) {
        return in;
    } else {
        return operator>><N + 1>(in >> std::get<N>(a), a);
    }
}
// vector
template <typename T>
std::istream& operator>>(std::istream& in, std::vector<T>& a) {
    for (auto it = a.begin(); it != a.end(); ++it) in >> *it;
    return in;
}
// array
template <typename T, size_t N>
std::istream& operator>>(std::istream& in, std::array<T, N>& a) {
    for (auto it = a.begin(); it != a.end(); ++it) in >> *it;
    return in;
}
template <typename ...Args>
void read(Args &...args) {
    (std::cin >> ... >> args);
}

// ! integral utilities

// Returns pow(-1, n)
template <typename T>
constexpr inline int pow_m1(T n) {
    return -(n & 1) | 1;
}
// Returns pow(-1, n)
template <>
constexpr inline int pow_m1<bool>(bool n) {
    return -int(n) | 1;
}

// Returns floor(x / y)
template <typename T>
constexpr inline T fld(const T x, const T y) {
    return (x ^ y) >= 0 ? x / y : (x - (y + pow_m1(y >= 0))) / y;
}
template <typename T>
constexpr inline T cld(const T x, const T y) {
    return (x ^ y) <= 0 ? x / y : (x + (y + pow_m1(y >= 0))) / y;
}

template <typename T, suisen::constraints_t<suisen::is_nbit<T, 16>> = nullptr>
__attribute__((target("popcnt"))) constexpr inline int popcount(const T x) { return _mm_popcnt_u32(x); }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 32>> = nullptr>
__attribute__((target("popcnt"))) constexpr inline int popcount(const T x) { return _mm_popcnt_u32(x); }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 64>> = nullptr>
__attribute__((target("popcnt"))) constexpr inline int popcount(const T x) { return _mm_popcnt_u64(x); }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 16>> = nullptr>
constexpr inline int count_lz(const T x) { return x ? __builtin_clz(x) : suisen::bit_num<T>; }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 32>> = nullptr>
constexpr inline int count_lz(const T x) { return x ? __builtin_clz(x) : suisen::bit_num<T>; }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 64>> = nullptr>
constexpr inline int count_lz(const T x) { return x ? __builtin_clzll(x) : suisen::bit_num<T>; }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 16>> = nullptr>
constexpr inline int count_tz(const T x) { return x ? __builtin_ctz(x) : suisen::bit_num<T>; }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 32>> = nullptr>
constexpr inline int count_tz(const T x) { return x ? __builtin_ctz(x) : suisen::bit_num<T>; }
template <typename T, suisen::constraints_t<suisen::is_nbit<T, 64>> = nullptr>
constexpr inline int count_tz(const T x) { return x ? __builtin_ctzll(x) : suisen::bit_num<T>; }
template <typename T>
constexpr inline int floor_log2(const T x) { return suisen::bit_num<T> -1 - count_lz(x); }
template <typename T>
constexpr inline int ceil_log2(const T x) { return floor_log2(x) + ((x & -x) != x); }
template <typename T>
constexpr inline int kth_bit(const T x, const unsigned int k) { return (x >> k) & 1; }
template <typename T>
constexpr inline int parity(const T x) { return popcount(x) & 1; }

// ! container

template <typename T, typename Comparator, suisen::constraints_t<suisen::is_comparator<Comparator, T>> = nullptr>
auto priqueue_comp(const Comparator comparator) {
    return std::priority_queue<T, std::vector<T>, Comparator>(comparator);
}

template <typename Iterable>
auto isize(const Iterable& iterable) -> decltype(int(iterable.size())) {
    return iterable.size();
}

template <typename T, typename Gen, suisen::constraints_t<suisen::is_same_as_invoke_result<T, Gen, int>> = nullptr>
auto generate_vector(int n, Gen generator) {
    std::vector<T> v(n);
    for (int i = 0; i < n; ++i) v[i] = generator(i);
    return v;
}
template <typename T>
auto generate_range_vector(T l, T r) {
    return generate_vector(r - l, [l](int i) { return l + i; });
}
template <typename T>
auto generate_range_vector(T n) {
    return generate_range_vector(0, n);
}

template <typename T>
void sort_unique_erase(std::vector<T>& a) {
    std::sort(a.begin(), a.end());
    a.erase(std::unique(a.begin(), a.end()), a.end());
}

template <typename InputIterator, typename BiConsumer>
auto foreach_adjacent_values(InputIterator first, InputIterator last, BiConsumer f) -> decltype(f(*first++, *last), void()) {
    if (first != last) for (auto itr = first, itl = itr++; itr != last; itl = itr++) f(*itl, *itr);
}
template <typename Container, typename BiConsumer>
auto foreach_adjacent_values(Container c, BiConsumer f) -> decltype(c.begin(), c.end(), void()) {
    foreach_adjacent_values(c.begin(), c.end(), f);
}

// ! other utilities

// x <- min(x, y). returns true iff `x` has chenged.
template <typename T>
inline bool chmin(T& x, const T& y) {
    if (y >= x) return false;
    x = y;
    return true;
}
// x <- max(x, y). returns true iff `x` has chenged.
template <typename T>
inline bool chmax(T& x, const T& y) {
    if (y <= x) return false;
    x = y;
    return true;
}

template <typename T, std::enable_if_t<std::is_integral_v<T>, std::nullptr_t> = nullptr>
std::string bin(T val, int bit_num = -1) {
    std::string res;
    if (bit_num >= 0) {
        for (int bit = bit_num; bit-- > 0;) res += '0' + ((val >> bit) & 1);
    } else {
        for (; val; val >>= 1) res += '0' + (val & 1);
        std::reverse(res.begin(), res.end());
    }
    return res;
}

template <typename T, std::enable_if_t<std::is_integral_v<T>, std::nullptr_t> = nullptr>
std::vector<T> digits_low_to_high(T val, T base = 10) {
    std::vector<T> res;
    for (; val; val /= base) res.push_back(val % base);
    if (res.empty()) res.push_back(T{ 0 });
    return res;
}
template <typename T, std::enable_if_t<std::is_integral_v<T>, std::nullptr_t> = nullptr>
std::vector<T> digits_high_to_low(T val, T base = 10) {
    auto res = digits_low_to_high(val, base);
    std::reverse(res.begin(), res.end());
    return res;
}

template <typename T>
std::string join(const std::vector<T>& v, const std::string& sep, const std::string& end) {
    std::ostringstream ss;
    for (auto it = v.begin(); it != v.end();) {
        ss << *it;
        if (++it != v.end()) ss << sep;
    }
    ss << end;
    return ss.str();
}

namespace suisen {}
using namespace suisen;
using namespace std;

struct io_setup {
    io_setup(int precision = 20) {
        std::ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
        std::cout << std::fixed << std::setprecision(precision);
    }
} io_setup_ {};

// ! code from here

#include <cassert>
#include <array>

#include <cstdint>
#include <vector>

namespace suisen {
    class BitVector {
        using u8 = std::uint8_t;
    public:
        explicit BitVector(int n) : n(n), nl((n >> LOG_BLOCK_L) + 1), ns((n >> LOG_BLOCK_S) + 1), cum_l(nl, 0), cum_s(ns, 0), bits(ns, 0) {}
        BitVector() : BitVector(0) {}
        template <typename Gen, constraints_t<is_same_as_invoke_result<bool, Gen, int>> = nullptr>
        BitVector(int n, Gen gen) : BitVector(n) {
            build(gen);
        }
        BitVector& operator=(const BitVector& bv) {
            n = bv.n, nl = bv.nl, ns = bv.ns, cum_l = bv.cum_l, cum_s = bv.cum_s, bits = bv.bits;
            return *this;
        }
        BitVector& operator=(BitVector&& bv) {
            n = bv.n, nl = bv.nl, ns = bv.ns, cum_l = std::move(bv.cum_l), cum_s = std::move(bv.cum_s), bits = std::move(bv.bits);
            return *this;
        }
        template <typename Gen, constraints_t<is_same_as_invoke_result<bool, Gen, int>> = nullptr>
        void build(Gen gen) {
            int i = 0;
            for (int index_s = 1; index_s < ns; ++index_s) {
                int count = cum_s[index_s - 1];
                for (; i < index_s << LOG_BLOCK_S; ++i) {
                    bool b = gen(i);
                    bits[index_s - 1] |= b << (i & MASK_S);
                    count += b;
                }
                if (index_s & ((1 << (LOG_BLOCK_L - LOG_BLOCK_S)) - 1)) {
                    cum_s[index_s] = count;
                } else {
                    int index_l = i >> LOG_BLOCK_L;
                    cum_l[index_l] = cum_l[index_l - 1] + count;
                }
            }
            for (; i < n; ++i) bits[ns - 1] |= gen(i) << (i & MASK_S);
        }
        inline bool operator[](int i) const {
            return (bits[i >> LOG_BLOCK_S] >> (i & MASK_S)) & 1;
        }
        // returns the i'th val (i: 0-indexed)
        inline bool access(int i) const {
            return (*this)[i];
        }
        // returns the number of val in [0, i)
        inline int rank(bool val, int i) const {
            int res_1 = cum_l[i >> LOG_BLOCK_L] + cum_s[i >> LOG_BLOCK_S] + popcount8(bits[i >> LOG_BLOCK_S] & ((1 << (i & MASK_S)) - 1));
            return val ? res_1 : i - res_1;
        }
        // returns the number of val in [l, r)
        inline int rank(bool val, int l, int r) const {
            return rank(val, r) - rank(val, l);
        }
        // find the index of num'th val. (num: 1-indexed). if not exists, returns default_value.
        int select(bool val, int num, int default_value = -1) const {
            int l = -1, r = n + 1;
            while (r - l > 1) {
                int m = (l + r) >> 1;
                (rank(val, m) >= num ? r : l) = m;
            }
            return r == n + 1 ? default_value : r;
        }
    private:
        static constexpr int LOG_BLOCK_L = 8;
        static constexpr int LOG_BLOCK_S = 3;
        static constexpr int MASK_S = (1 << LOG_BLOCK_S) - 1;

        int n, nl, ns;
        std::vector<int> cum_l;
        std::vector<u8> cum_s, bits;

        static constexpr u8 popcount8(u8 x) {
            x = (x & 0b01010101) + ((x >> 1) & 0b01010101);
            x = (x & 0b00110011) + ((x >> 2) & 0b00110011);
            return (x & 0b00001111) + (x >> 4);
        }
    };
} // namespace suisen

namespace suisen {
    template <typename T, int bit_num = std::numeric_limits<std::make_unsigned_t<T>>::digits>
    struct WaveletMatrix {
        // default constructor
        WaveletMatrix() noexcept : n(0) {}
        // builds WaveletMatrix from generating function typed as (int) -> T
        template <typename Gen, constraints_t<is_same_as_invoke_result<T, Gen, int>> = nullptr>
        WaveletMatrix(int n, Gen generator) : n(n) {
            build(generator);
        }
        // builds WaveletMatrix from vector
        template <typename U, constraints_t<std::is_constructible<T, U>> = nullptr>
        WaveletMatrix(const std::vector<U>& a) : WaveletMatrix(a.size(), [&a](int i) { return T(a[i]); }) {}

        // builds WaveletMatrix from generating function typed as (int) -> T
        template <typename Gen, constraints_t<is_same_as_invoke_result<T, Gen, int>> = nullptr>
        void build(Gen generator) {
            std::vector<T> a(n), l(n), r(n);
            for (int i = 0; i < n; ++i) a[i] = generator(i);
            for (int log = bit_num - 1; log >= 0; --log) {
                bv[log] = BitVector(n, [&a, log](int i) -> bool { return (a[i] >> log) & 1; });
                int li = 0, ri = 0;
                for (int i = 0; i < n; ++i) {
                    ((a[i] >> log) & 1 ? r[ri++] : l[li++]) = a[i];
                }
                a.swap(l);
                std::copy(r.begin(), r.begin() + ri, a.begin() + li);
                mid[log] = li;
            }
        }
        // returns WaveletMatrix[i]
        T operator[](int i) const {
            T res = 0;
            for (int log = bit_num - 1; log >= 0; --log) {
                bool b = bv[log][i];
                res |= T(b) << log;
                i = b * mid[log] + bv[log].rank(b, i);
            }
            return res;
        }
        // returns WaveletMatrix[i]
        inline T access(int i) const {
            return (*this)[i];
        }
        // returns the number of `val` in WaveletMatrix[0, i).
        int rank(T val, int i) const {
            check_value_bounds(val);
            int l = 0, r = i;
            for (int log = bit_num - 1; log >= 0; --log) succ(l, r, (val >> log) & 1, log);
            return r - l;
        }
        // returns the k'th smallest value in WaveletMatrix[l, r) (k : 0-indexed)
        T range_kth_smallest(int l, int r, int k, T default_value = T(-1)) const {
            if (k < 0 or k >= r - l) return default_value;
            T res = 0;
            for (int log = bit_num - 1; log >= 0; --log) {
                int cnt_0 = bv[log].rank(false, l, r);
                bool bit = k >= cnt_0;
                succ(l, r, bit, log);
                res |= T(bit) << log;
                k -= bit * cnt_0;
            }
            return res;
        }
        // returns the k'th largest value in WaveletMatrix[l, r) (k : 0-indexed)
        inline T range_kth_largest(int l, int r, int k, T default_value = T(-1)) const {
            return range_kth_smallest(l, r, r - l - 1 - k, default_value);
        }
        // returns the minimum value in WaveletMatrix[l, r)
        inline T range_min(int l, int r) const {
            assert(l < r);
            return range_kth_smallest(l, r, 0);
        }
        // returns the maximum value in WaveletMatrix[l, r)
        inline T range_max(int l, int r) const {
            assert(l < r);
            return range_kth_largest(l, r, 0);
        }
        // returns the number of v in WaveletMatrix[l, r) s.t. v < upper
        int range_freq(int l, int r, T upper) const {
            if (r <= l) return 0;
            check_value_bounds(upper);
            int res = 0;
            for (int log = bit_num - 1; log >= 0; --log) {
                bool b = (upper >> log) & 1;
                if (b) res += bv[log].rank(false, l, r);
                succ(l, r, b, log);
            }
            return res;
        }
        // returns the number of v in WaveletMatrix[l, r) s.t. lower <= v < upper
        inline int range_freq(int l, int r, T lower, T upper) const {
            if (lower >= upper) return 0;
            return range_freq(l, r, upper) - range_freq(l, r, lower);
        }
        // returns the minimum value v in WaveletMatrix[l, r) s.t. lower <= v
        inline T range_min_geq(int l, int r, T lower, T default_value = T(-1)) const {
            int cnt = range_freq(l, r, lower);
            return cnt >= r - l ? default_value : range_kth_smallest(l, r, cnt);
        }
        // returns the minimum value v in WaveletMatrix[l, r) s.t. lower < v
        inline T range_min_gt(int l, int r, T lower, T default_value = T(-1)) const {
            return lower == MAX ? default_value : range_min_geq(l, r, lower + 1);
        }
        // returns the maximum value v in WaveletMatrix[l, r) s.t. v < upper
        inline T range_max_lt(int l, int r, T upper, T default_value = T(-1)) const {
            int cnt = range_freq(l, r, upper);
            return cnt == 0 ? default_value : range_kth_smallest(l, r, cnt - 1);
        }
        // returns the maximum value v in WaveletMatrix[l, r) s.t. v <= upper
        inline T range_max_leq(int l, int r, T upper, T default_value = T(-1)) const {
            if (r >= l) return default_value;
            return upper == MAX ? range_max(l, r) : range_max_lt(l, r, upper + 1);
        }
    protected:
        WaveletMatrix(int n) noexcept : n(n) {}
    private:
        static_assert(bit_num > 0);
        static constexpr T MAX = bit_num == std::numeric_limits<T>::digits ? std::numeric_limits<T>::max() : (T(1) << bit_num) - 1;

        int n;
        std::array<BitVector, bit_num> bv;
        std::array<int, bit_num> mid;

        inline void succ(int& l, int& r, const bool b, const int log) const {
            l = b * mid[log] + bv[log].rank(b, l);
            r = b * mid[log] + bv[log].rank(b, r);
        }

        static constexpr void check_value_bounds(T val) {
            assert((val >> bit_num) == 0);
        }
    };
} // namespace suisen

int main() {
    input(int, n, q);

    vector<string> s(n), rs(n);

    rep(i, n) {
        read(s[i]);
    }
    sort(all(s));
    rep(i, n) {
        rs[i] = s[i];
        reverse(all(rs[i]));
    }
    vector<int> rp(n);
    iota(all(rp), 0);
    sort(all(rp), [&](int i, int j) { return rs[i] < rs[j]; });

    vector<int> dat(n);
    rep(i, n) {
        dat[rp[i]] = i;
    }
    WaveletMatrix<int, 17> wm(dat);

    auto search_prefix = [&](string pre) {
        const int len = pre.size();
        int res_l, res_r;
        {
            int l = -1, r = n;
            while (r - l > 1) {
                int m = (l + r) >> 1;
                (s[m] < pre ? l : r) = m;
            }
            res_l = r;
        }
        ++pre.back();
        {
            int l = -1, r = n;
            while (r - l > 1) {
                int m = (l + r) >> 1;
                (s[m] < pre ? l : r) = m;
            }
            res_r = r;
        }
        return make_pair(res_l, res_r);
    };
    auto search_suffix = [&](string suf) {
        reverse(all(suf));
        const int len = suf.size();
        int res_l, res_r;
        {
            int l = -1, r = n;
            while (r - l > 1) {
                int m = (l + r) >> 1;
                (rs[rp[m]] < suf ? l : r) = m;
            }
            res_l = r;
        }
        ++suf.back();
        {
            int l = -1, r = n;
            while (r - l > 1) {
                int m = (l + r) >> 1;
                (rs[rp[m]] < suf ? l : r) = m;
            }
            res_r = r;
        }
        return make_pair(res_l, res_r);
    };

    loop(q) {
        input(string, pre, suf);
        auto [il, ir] = search_prefix(pre);
        auto [vl, vr] = search_suffix(suf);
        print(wm.range_freq(il, ir, vl, vr));
    }

    return 0;
}
accuracy: 1
time_ms: 170
memory_kb: 21132
final_rank: 3

code_snippet: #include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <ctime>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <vector>
#define setIO(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout)
#define closefile fclose(stdin), fclose(stdout)
#define m_p make_pair
#define sz(x) (int)x.size()
#define see(x) cerr << x << " "
#define seeln(x) cerr << x << endl
#define out(x) cerr << #x << " = " << x << " "
#define outln(x) cerr << #x << " = " << x << endl
#define outarr(x, l, r) {cerr << #x"[" << l << " ~ " << r << "] = "; for (int _i = l; _i <= r; ++_i) cerr << x[_i] << " "; cerr << endl;}
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define gc() getchar()
//#define gc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
char buf[1 << 21], *p1 = buf, *p2 = buf;
template <class T> void read(T &x) {
    x = 0; int c = gc(); int flag = 0;
    while (c < '0' || c > '9') flag |= (c == '-'), c = gc();
    while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + (c ^ 48), c = gc();
    if (flag) x = -x;
}
template <class T> bool checkmax(T &a, T b) {return a < b ? a = b, 1 : 0;}
template <class T> bool checkmin(T &a, T b) {return b < a ? a = b, 1 : 0;}
constexpr int N = 100005;
int n, q, m = 0;
int c[N];
string a[N], A[N];
pair<string, int> b[N];
int rt[N], cnt = 0;
int sum[N << 5], lson[N << 5], rson[N << 5];
void push_up(int x) {
    sum[x] = sum[lson[x]] + sum[rson[x]];
}

void update(int &x, int y, int l, int r, int p) {
    x = ++cnt;
    sum[x] = sum[y], lson[x] = lson[y], rson[x] = rson[y];
    if (l == r) {
        sum[x] += 1;
        return;
    }
    int mid = (l + r) >> 1;
    if (p <= mid) update(lson[x], lson[y], l, mid, p);
    else update(rson[x], rson[y], mid + 1, r, p);
    push_up(x);
}

int query(int x, int l, int r, int L, int R) {
    if (!x) return 0;
    if (L <= l && r <= R) return sum[x];
    int mid = (l + r) >> 1, ans = 0;
    if (L <= mid) ans += query(lson[x], l, mid, L, R);
    if (R > mid) ans += query(rson[x], mid + 1, r, L, R);
    return ans;
}

void init() {
    cin >> n >> q;
    for (int i = 1; i <= n; ++i) cin >> a[i];
    sort(a + 1, a + n + 1);
    for (int i = 1; i <= n; ++i) {
        b[i] = {a[i], i};
        reverse(b[i].first.begin(), b[i].first.end());
    }
    sort(b + 1, b + n + 1);
    for (int i = 1; i <= n; ++i) {
        if (i == 1 || b[i].first != b[i - 1].first) {
            c[b[i].second] = ++m;
            A[m] = b[i].first;
        } else {
            c[b[i].second] = c[b[i - 1].second];
        }
    }
    for (int i = 1; i <= n; ++i) {
        update(rt[i], rt[i - 1], 1, m, c[i]);
    }
}

void solve() {
    string s, t;
    while (q--) {
        cin >> s >> t;
        int l = lower_bound(a + 1, a + n + 1, s) - a;
        int r = lower_bound(a + 1, a + n + 1, s + "|") - a - 1;
        if (l > r) {
            printf("0\n");
            continue;
        }
        reverse(t.begin(), t.end());
        int vl = lower_bound(A + 1, A + m + 1, t) - A;
        int vr = lower_bound(A + 1, A + m + 1, t + "|") - A - 1;
        int ans = 0;
        if (vl <= vr) {
            ans += query(rt[r], 1, m, vl, vr);
            ans -= query(rt[l - 1], 1, m, vl, vr);
        }
        /*for (int i = l; i <= r; ++i) {
            if (c[i] >= vl && c[i] <= vr) {
                ans += 1;
            }
        }*/
        printf("%d\n", ans);
    }
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    init();
    solve();
    return 0;
}
accuracy: 1
time_ms: 200
memory_kb: 52932
final_rank: 7

code_snippet: #include "iostream"
#include "climits"
#include "list"
#include "queue"
#include "stack"
#include "set"
#include "functional"
#include "algorithm"
#include "string"
#include "map"
#include "unordered_map"
#include "unordered_set"
#include "iomanip"
#include "cmath"
#include "random"
#include "bitset"
#include "cstdio"
#include "numeric"
#include "cassert"
#include "ctime"

using namespace std;

//constexpr long long int MOD = 1000000007;
constexpr long long int MOD = 998244353;
constexpr long double EPS = 1e-12;

//int N, M, K, T, H, W, L, R;
long long int N, M, K, T, H, W, L, R;

class SuffixArray {
public:
	vector<int>ans;
	vector<int>id;
	vector<int>lcp;
	void InducedSort(vector<int>&ret,const vector<int>& v,const vector<int>&large, vector<int>&lft,vector<int>&rht) {
		for (int i = 0; i < v.size(); i++) {
			if (ret[i] == -1)continue;
			if (ret[i] == 0)continue;
			if (!large[ret[i] - 1])continue;
			ret[lft[v[ret[i] - 1]]++] = ret[i] - 1;
		}
		for (int i = v.size() - 1; i >= 0; i--) {
			if (ret[i] == -1)continue;
			if (ret[i] == 0)continue;
			if (large[ret[i] - 1])continue;
			ret[--rht[v[ret[i] - 1]]] = ret[i] - 1;
		}
	}
	vector<int> Solve(vector<int>v, int mx) {
		vector<int>ret;
		vector<int>large;
		vector<int>num;
		vector<int>nx_lms;
		vector<bool>lms;
		vector<int>rht;
		vector<int>lft;
		if (v.size() == 1) {
			return vector<int>(1);
		}
		large.resize((v.size()));
		nx_lms.resize(v.size(), v.size() - 1);
		lms.resize(v.size());
		lms.back() = true;
		for (int i = v.size() - 2; i >= 0; i--) {
			if (v[i] > v[i + 1]) {
				large[i] = 1;
			}
			else if (v[i] < v[i + 1]) {
				large[i] = 0;
			}
			else {
				large[i] = large[i + 1];
			}
		}
		for (int i = v.size() - 2; i > 0; i--) {
			if (large[i - 1] && !large[i]) {
				lms[i] = true;
				nx_lms[i - 1] = i;
			}
			else {
				nx_lms[i - 1] = nx_lms[i];
			}
		}
		ret.resize(v.size(), -1);
		num.resize(mx + 1);
		lft.resize(mx + 1);
		rht.resize(mx + 1);
		for (auto i : v) {
			num[i]++;
		}
		for (int i = 1; i <= mx; i++) {
			num[i] += num[i - 1];
		}
		rht[0] = num[0];
		for (int i = 1; i <= mx; i++) {
			rht[i] = num[i];
			lft[i] = num[i - 1];
		}
		for (int i = 1; i < v.size(); i++) {
			if (lms[i]) {
				ret[--rht[v[i]]] = i;
			}
		}
		for (int i = 0; i <= mx; i++) {
			rht[i] = num[i];
		}
		InducedSort(ret,v,large,lft,rht);
		vector<int>nxv;
		int nxmx = -1;
		vector<int>conv(v.size());
		vector<int>nxp;
		for (int i = 0; i + 1 < v.size(); i++) {
			if (large[i] && !large[i + 1]) {
				nxp.push_back(i + 1);
			}
		}
		vector<int>bef;
		for (int i = 0; i < v.size(); i++) {
			if (lms[ret[i]]) {
				vector<int> aft;
				for (int j = ret[i]; j <= nx_lms[ret[i]]; j++) {
					aft.push_back(v[j]);
				}
				if (bef != aft) {
					nxmx++;
					bef = aft;
				}
				conv[ret[i]] = nxmx;
			}
		}
		for (int i = 0; i < v.size(); i++) {
			if (lms[i]) {
				nxv.push_back(conv[i]);
			}
		}

		auto nxret = Solve(nxv, nxmx);

		for (auto& i : ret)i = -1;

		rht[0] = num[0];
		lft[0] = 0;
		for (int i = 1; i <= mx; i++) {
			rht[i] = num[i];
			lft[i] = num[i - 1];
		}


		for (int i = nxret.size() - 1; i >= 0; i--) {
			ret[--rht[v[nxp[nxret[i]]]]] = nxp[nxret[i]];
		}

		for (int i = 0; i <= mx; i++) {
			rht[i] = num[i];
		}

		InducedSort(ret,v,large,lft,rht);
		return ret;
	}
	SuffixArray(string s) {
		vector<int>v;
		int mx = 0;
		for (auto i : s) {
			v.push_back(i + 1);
			mx = max(mx, i + 1);
		}
		v.push_back(0);
		ans = Solve(v, mx);
		ans.erase(ans.begin());
		id.resize(ans.size());
		lcp.resize(ans.size());
		for (int i = 0; i < ans.size(); i++) {
			id[ans[i]] = i;
		}
		for (int i = 0; i < id.size(); i++) {
			int nx = id[i];
			if (nx + 1 == id.size())continue;
			nx = ans[nx + 1];
			int idx = i;
			if (i && lcp[id[i - 1]]) {
				lcp[id[i]] = lcp[id[i - 1]] - 1;
				nx += lcp[id[i]];
				idx += lcp[id[i]];
			}
			while (nx < id.size() && i < id.size() && s[idx] == s[nx]) {
				lcp[id[i]]++;
				nx++;
				idx++;
			}
		}
	}
};

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);

	cin >> N >> M;
	vector<string>s(N);
	for (auto& i : s)cin >> i;
	string t;

	for (auto i : s) {
		t += i;
		t.push_back('#');
		t += i;
		t.push_back('!');
	}
	vector<int>idx;
	vector<int>num;
	int border = t.size();
	while (M--) {
		idx.push_back(t.size());
		string a, b;
		cin >> a >> b;
		num.push_back(a.size() + b.size() + 1);
		t += b;
		t.push_back('#');
		t += a;
		t.push_back(0);
	}
	SuffixArray sa(t);
	//	for (auto i : sa.id)cout << i << " ";
	//	cout << endl;
	for (int i = 0; i < idx.size(); i++) {
		int p = sa.id[idx[i]];
		int ret = 0;
		while (p < sa.lcp.size()) {
			//	cout << i << " " << sa.lcp[p] << endl;
			if (sa.lcp[p] >= num[i]) {
				p++;
				if (sa.ans[p] < border)ret++;
			}
			else break;
		}
		cout << ret << endl;
	}
}
accuracy: 1
time_ms: 850
memory_kb: 212744
final_rank: 13

code_snippet: #pragma GCC ta g("avx2")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#define DEBUG
#ifdef DEBUG
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    os << '{';
    for(int i = 0; i < (int)v.size(); i++) {
        if(i) { os << ','; }
        os << v[i];
    }
    os << '}';
    return os;
}
void debugg() { cerr << endl; }
template <class T, class... Args>
void debugg(const T &x, const Args &... args) {
    cerr << " " << x;
    debugg(args...);
}
#define debug(...)                                                             \
    cerr << __LINE__ << " [" << #__VA_ARGS__ << "]: ", debugg(__VA_ARGS__)
#define dump(x) cerr << __LINE__ << " " << #x << " = " << (x) << endl
#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef pair<int,int> pii;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(int i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T> inline void print(T &a){
    int sz = a.size();
    for(auto itr = a.begin(); itr != a.end(); itr++){
		cout << *itr;
        sz--;
        if(sz) cout << " ";
	}
    cout << "\n";
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){
	cout << a << " " << b << "\n";
}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << a << " " << b << " " << c << "\n";
}
void mark() {cout << "#" << "\n";}
ll pcount(ll x) {return __builtin_popcountll(x);}
//#include <atcoder/maxflow>
//using namespace atcoder;
const int inf = (1<<30)-1;
const ll linf = 1LL<<61;
const int MAX = 510000;
int dy[8] = {0,1,0,-1,1,-1,-1,1};
int dx[8] = {-1,0,1,0,1,-1,1,-1};
const double pi = acos(-1);
const double eps = 1e-9;
//const int mod = 1e9 + 7;
const int mod = 998244353;

template<typename T> struct BIT{
	vector<T> dat;
	ll sz;
	//all 1-indexed
	BIT(ll sz) : sz(sz){
		dat.assign(++sz, 0);
	}

	T sum(ll k){
		T ret = 0;
		for(++k; k > 0; k -= k & -k) ret += dat[k];
		return (ret);
	}

	void add(ll k, T x){
		for(++k; k < dat.size(); k += k & -k) dat[k] += x;
	}
	
	ll get(T k){
		if(k <= 0) return 0; 
		ll ret = 0;
		int n = 1; while(n < sz) n *= 2;
		for(int i=n/2; i>0; i/=2){
			if(ret+i < sz && dat[ret+i] < k){
				k -= dat[ret+i];
				ret += i;
			}
		}
		return ret;
	}
};

int main(){
	int n,q; cin >> n >> q;
	vs s(n); rep(i,n) cin >> s[i];
	BIT<int> bit(n);
	sort(all(s));
	vector<pair<string,int>> rev(n);
	vl rid(n);
	rep(i,n){
		rev[i] = {s[i],i};
		reverse(all(rev[i].first));
	}
	sort(all(rev));
	rep(i,n) rid[rev[i].second] = i;
	vector<tuple<int,int,int,int>> query(q);
	rep(i,q){
		string x,y; cin >> x >> y; reverse(all(y));
		int l = -1, r = n;
		int L,R;
		while(r-l > 1){
			int m = (l+r) / 2;
			if(s[m].substr(0,x.size()) < x) l = m;
			else r = m;
		}
		L = r;
		l = -1, r = n;
		while(r-l > 1){
			int m = (l+r) / 2;
			if(s[m].substr(0,x.size()) <= x) l = m;
			else r = m;
		}
		R = r;
		int L2,R2;
		l = -1, r = n;
		while(r-l > 1){
			int m = (l+r) / 2;
			if(rev[m].first.substr(0,y.size()) < y) l = m;
			else r = m;
		}
		L2 = r;
		l = -1, r = n;
		while(r-l > 1){
			int m = (l+r) / 2;
			if(rev[m].first.substr(0,y.size()) <= y) l = m;
			else r = m;
		}
		R2 = r;
		query[i] = tie(L,R,L2,R2);
	}
	vector<vvl> dec(n), inc(n);
	rep(i,q){
		int L,R,L2,R2;
		tie(L,R,L2,R2) = query[i];
		if(L>0) dec[L-1].emplace_back(vl{L2,R2-1,i});
		if(R>0) inc[R-1].emplace_back(vl{L2,R2-1,i});
	}
	vl ans(q,0);
	rep(i,n){
		bit.add(rid[i],1);
		for(vl v : dec[i]){
			ans[v[2]] -= bit.sum(v[1]) - bit.sum(v[0]-1);
		}
		for(vl v : inc[i]){
			ans[v[2]] += bit.sum(v[1]) - bit.sum(v[0]-1);
		}
	}
	rep(i,q) cout << ans[i] << "\n";
}
accuracy: 1
time_ms: 200
memory_kb: 38944
final_rank: 5

code_snippet: #pragma GCC ta g("avx2")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#define DEBUG
#ifdef DEBUG
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    os << '{';
    for(int i = 0; i < (int)v.size(); i++) {
        if(i) { os << ','; }
        os << v[i];
    }
    os << '}';
    return os;
}
void debugg() { cerr << endl; }
template <class T, class... Args>
void debugg(const T &x, const Args &... args) {
    cerr << " " << x;
    debugg(args...);
}
#define debug(...)                                                             \
    cerr << __LINE__ << " [" << #__VA_ARGS__ << "]: ", debugg(__VA_ARGS__)
#define dump(x) cerr << __LINE__ << " " << #x << " = " << (x) << endl
#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef pair<int,int> pii;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(int i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T> inline void print(T &a){
    int sz = a.size();
    for(auto itr = a.begin(); itr != a.end(); itr++){
		cout << *itr;
        sz--;
        if(sz) cout << " ";
	}
    cout << "\n";
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){
	cout << a << " " << b << "\n";
}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << a << " " << b << " " << c << "\n";
}
void mark() {cout << "#" << "\n";}
ll pcount(ll x) {return __builtin_popcountll(x);}
//#include <atcoder/maxflow>
//using namespace atcoder;
const int inf = (1<<30)-1;
const ll linf = 1LL<<61;
const int MAX = 510000;
int dy[8] = {0,1,0,-1,1,-1,-1,1};
int dx[8] = {-1,0,1,0,1,-1,1,-1};
const double pi = acos(-1);
const double eps = 1e-9;
//const int mod = 1e9 + 7;
const int mod = 998244353;

template<typename T> struct BIT{
	vector<T> dat;
	ll sz;
	//all 1-indexed
	BIT(ll sz) : sz(sz){
		dat.assign(++sz, 0);
	}

	T sum(ll k){
		T ret = 0;
		for(++k; k > 0; k -= k & -k) ret += dat[k];
		return (ret);
	}

	void add(ll k, T x){
		for(++k; k < dat.size(); k += k & -k) dat[k] += x;
	}
	
	ll get(T k){
		if(k <= 0) return 0; 
		ll ret = 0;
		int n = 1; while(n < sz) n *= 2;
		for(int i=n/2; i>0; i/=2){
			if(ret+i < sz && dat[ret+i] < k){
				k -= dat[ret+i];
				ret += i;
			}
		}
		return ret;
	}
};

int main(){
	int n,q; cin >> n >> q;
	vs s(n); rep(i,n) cin >> s[i];
	BIT<int> bit(n);
	sort(all(s));
	vector<pair<string,int>> rev(n);
	vl rid(n);
	rep(i,n){
		rev[i] = {s[i],i};
		reverse(all(rev[i].first));
	}
	sort(all(rev));
	rep(i,n) rid[rev[i].second] = i;
	vector<tuple<int,int,int,int>> query(q);
	rep(i,q){
		string x,y; cin >> x >> y; reverse(all(y));
		int l = -1, r = n;
		int L,R;
		while(r-l > 1){
			int m = (l+r) / 2;
			if(s[m].substr(0,x.size()) < x) l = m;
			else r = m;
		}
		L = r;
		l = -1, r = n;
		while(r-l > 1){
			int m = (l+r) / 2;
			if(s[m].substr(0,x.size()) <= x) l = m;
			else r = m;
		}
		R = r;
		int L2,R2;
		l = -1, r = n;
		while(r-l > 1){
			int m = (l+r) / 2;
			if(rev[m].first.substr(0,y.size()) < y) l = m;
			else r = m;
		}
		L2 = r;
		l = -1, r = n;
		while(r-l > 1){
			int m = (l+r) / 2;
			if(rev[m].first.substr(0,y.size()) <= y) l = m;
			else r = m;
		}
		R2 = r;
		query[i] = tie(L,R,L2,R2);
	}
	vector<vvl> dec(n), inc(n);
	rep(i,q){
		int L,R,L2,R2;
		tie(L,R,L2,R2) = query[i];
		if(L>0) dec[L-1].emplace_back(vl{L2,R2-1,i});
		inc[R-1].emplace_back(vl{L2,R2-1,i});
	}
	vl ans(q,0);
	rep(i,n){
		bit.add(rid[i],1);
		for(vl v : dec[i]){
			ans[v[2]] -= bit.sum(v[1]) - bit.sum(v[0]-1);
		}
		for(vl v : inc[i]){
			ans[v[2]] += bit.sum(v[1]) - bit.sum(v[0]-1);
		}
	}
	rep(i,q) cout << ans[i] << "\n";
}
accuracy: 0.3333333333333333
time_ms: 80
memory_kb: 19380
final_rank: 20