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>
using namespace std;
string str = "ACGU";
map<char, int> mp = {{'A', 0}, {'C', 1}, {'G', 2}, {'U', 3}};
struct Node {
    int to[4] = {};
    int link = 0;
    int term = 0;
};
const int N = 100100;
const int M = 4000100;
Node nodes[M];
int numberOfNodes;
Node& node(int i) {
    assert(0 <= i && i <= numberOfNodes);
    return nodes[i]; 
}
int createNode() {
    nodes[++numberOfNodes] = Node();
    return numberOfNodes;
}
int getNext(int v, char c) {
    return node(v).to[mp[c]];
} 
 
int root = createNode();
int getLink(int v, char c) {
    if (!v) return root;
    if (getNext(v, c)) return getNext(v, c);
    return getLink(node(v).link, c);
}
void addWord(string s, int x) {
    int v = root;
    for (char c : s) {
        if (!getNext(v, c))
            node(v).to[mp[c]] = createNode();
        v = getNext(v, c);
    }
    node(v).term += x;
}
bool checkWord(string s) {
    int v = root;
    for (char c : s) {
        if (!getNext(v, c)) return false;
        v = getNext(v, c);
    }
    return true;
}
void build() {
    queue<int> q;
    q.push(root);
    while (!q.empty()) {
        int s = q.front();
        q.pop();
        for (int x = 0; x < 4; x++) {
            int nxt = node(s).to[x];
            if (!nxt) continue;
            node(nxt).link = getLink(node(s).link, str[x]); 
            q.push(nxt);
        }
    }
}
struct Graph {
    vector<int> e[M];
    int ord[M];
    int tin[M], tout[M], T;
    void dfs(int s, int p) {
        tin[s] = ++T;
        ord[T] = s;
        for (int to : e[s]) {
            if (to == p) continue;
            dfs(to, s);
        }
        tout[s] = T;
    }
};
struct Fenwick {
    int tr[M];
    void update(int pos, int val) {
        for (; pos < M; pos += (pos & -pos))
            tr[pos] += val;
    }
    int get(int l, int r) {
        int res = 0;
        for (; r; r -= (r & -r))
            res += tr[r];
        for (--l; l; l -= (l & -l))
            res -= tr[l];
        return res;
    }
};
struct Query {
    int l;
    int r;
    int mul;
    int inx;
};
int n, m;
Graph g1, g2;
Fenwick fnw;
int res[N];
vector<Query> qrs[M];
pair<string, string> queries[M];
int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    
    cin >> n >> m;
    
    for (int i = 0; i < n; i++) {
        string s;
        cin >> s;
        addWord(s, +1);
    }
    
    for (int i = 0; i < m; i++) {
        string p, q;
        cin >> p >> q;
        addWord(q, 0);
        queries[i] = {p, q};
    }
    build();
    for (int i = 1; i <= numberOfNodes; i++) {
        for (int x = 0; x < 4; x++) {
            int nxt = node(i).to[x];
            if (nxt)
                g1.e[i].push_back(nxt);
        }
        if (node(i).link) 
            g2.e[node(i).link].push_back(i);
    }    
    g1.dfs(1, 1);
    g2.dfs(1, 1);
    
    for (int i = 0; i < m; i++) {
        auto [p, q] = queries[i];
        if (!checkWord(p)) continue;
        int u = root, v = root;
        for (char c : p) u = getNext(u, c);
        for (char c : q) v = getNext(v, c);
        qrs[g1.tin[u] - 1].push_back({g2.tin[v], g2.tout[v], -1, i});
        qrs[g1.tout[u]].push_back({g2.tin[v], g2.tout[v], +1, i});
    }
    for (int i = 0; i < M; i++) {
        int v = g1.ord[i];
        if (v) 
            fnw.update(g2.tin[v], node(v).term);
        for (auto q : qrs[i]) {
            int val = fnw.get(q.l, q.r);
            res[q.inx] += q.mul * val;
        }
    }
    for (int i = 0; i < m; i++)
        cout << res[i] << '\n';
}
| # | 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... |