This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <bits/stdc++.h>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef long double ld;
typedef complex<ld> cd;
typedef pair<int, int> pi;
typedef pair<ll,ll> pl;
typedef pair<ld,ld> pd;
typedef vector<int> vi;
typedef vector<ld> vd;
typedef vector<ll> vl;
typedef vector<pi> vpi;
typedef vector<pl> vpl;
typedef vector<cd> vcd;
template <class T> using Tree = tree<T, null_type, less<T>, rb_tree_tag,tree_order_statistics_node_update>;
#define FOR(i, a, b) for (int i=a; i<(b); i++)
#define F0R(i, a) for (int i=0; i<(a); i++)
#define FORd(i,a,b) for (int i = (b)-1; i >= a; i--)
#define F0Rd(i,a) for (int i = (a)-1; i >= 0; i--)
#define sz(x) (int)(x).size()
#define mp make_pair
#define pb push_back
#define f first
#define s second
#define lb lower_bound
#define ub upper_bound
#define all(x) x.begin(), x.end()
const int MOD = 1000000007;
const ll INF = 1e18;
const int MX = 100001;
int cat(char c) {
switch(c) {
case 'A':
return 0;
case 'C':
return 1;
case 'G':
return 2;
default:
return 3;
}
}
template<int MX> struct tri {
int trie[MX][4], nex = 0; // easily changed to character
int sz[MX], EN[MX];
tri() {
memset(trie,0,sizeof trie);
}
void ins(string t) { // insert or delete
int cur = 0; sz[cur] ++;
for (char c: t) {
int C = cat(c);
if (!trie[cur][C]) {
trie[cur][C] = ++nex;
// if U
}
cur = trie[cur][C];
sz[cur] ++;
}
EN[cur] ++;
}
pi getBound(string t) {
int cur = 0, st = 0;
for (char c: t) {
int C = cat(c);
if (!trie[cur][C]) return {0,-1};
F0R(i,C) if (trie[cur][i]) {
// cout << "OOPS " << sz(t) << " " << cur << " " << i << " " << trie[cur][i] << "\n";
st += sz[trie[cur][i]];
}
st += EN[cur];
// cout << "HUH " << cur << " " << EN[cur] << "\n";
cur = trie[cur][C];
}
return {st+1,st+sz[cur]};
}
};
tri<2000001> t0, t1;
template<class T, int SZ> struct BIT {
T bit[SZ+1];
BIT() { memset(bit,0,sizeof bit); }
void upd(int k, T val) { // add val to index k
for( ;k <= SZ; k += (k&-k)) bit[k] += val;
}
T query(int k) {
T temp = 0;
for (;k > 0;k -= (k&-k)) temp += bit[k];
return temp;
}
T query(int l, int r) { return query(r)-query(l-1); } // range query [l,r]
};
BIT<int,MX> B;
int N,M, ans[MX], beg[MX], en[MX];
vector<pair<string,int>> v0, v1;
vector<array<int,3>> v[MX];
vi ad[MX];
void input() {
ios_base::sync_with_stdio(0); cin.tie(0);
cin >> N >> M;
FOR(i,1,N+1) {
string s; cin >> s;
t0.ins(s); v0.pb({s,i});
reverse(all(s));
t1.ins(s); v1.pb({s,i});
}
sort(all(v0)), sort(all(v1));
F0R(i,N) {
// cout << v0[i].f << " " << t0.getBound(v0[i].f).f << " " << t0.getBound(v0[i].f).s << "\n";
beg[v0[i].s] = i+1;
en[v1[i].s] = i+1;
}
FOR(i,1,N+1) {
ad[beg[i]].pb(en[i]);
// cout << beg[i] << " " << en[i] << "\n";
}
}
int main() {
input();
F0R(i,M) {
string P, Q; cin >> P >> Q; reverse(all(Q));
pi x = t0.getBound(P), y = t1.getBound(Q);
// cout << x.f << " " << x.s << " " << y.f << " " << y.s << "\n";
if (x.f > x.s || y.f > y.s) continue;
v[x.f-1].pb({y.s,-1,i});
v[x.f-1].pb({y.f-1,1,i});
v[x.s].pb({y.s,1,i});
v[x.s].pb({y.f-1,-1,i});
}
FOR(i,1,N+1) {
for (int y: ad[i]) B.upd(y,1);
for (auto a: v[i]) ans[a[2]] += a[1]*B.query(a[0]);
}
F0R(i,M) cout << ans[i] << "\n";
}
/* Look for:
* the exact constraints (multiple sets are too slow for n=10^6 :( )
* special cases (n=1?)
* overflow (ll vs int?)
* array bounds
*/
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |