Submission #1131571

#TimeUsernameProblemLanguageResultExecution timeMemory
1131571snowmelSelling RNA Strands (JOI16_selling_rna)C++20
35 / 100
1037 ms407000 KiB
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int maxN = 1e5 + 10;
int N, M;
string A[maxN], P[maxN], Q[maxN];
namespace sub1 {
bool check() { return N <= 100 && M <= 100; }
void solve() {
    for(int i = 0; i < M; ++i) {
        int cnt = 0;
        for(int j = 0; j < N; ++j) {
            if(A[j].size() < P[i].size() || A[j].size() < Q[i].size()) continue;
            if(A[j].substr(0, P[i].size()) == P[i] && A[j].substr(A[j].size() - Q[i].size(), A[j].size()) == Q[i]) ++cnt;
        }
        cout << cnt << "\n";
    }
}
};
namespace sub2 {
const ll base1 = 257;
const ll base2 = 263;
const ll MOD = 1e9 + 7;
bool check() { return N <= 5000 && M <= 5000; }
ll qpow(ll x, ll k) {
    ll res = 0;
    while(k) {
        if(k & 1) res = res * x % MOD;
        x = x * x % MOD;
        k >>= 1;
    }
    return res;
}
void solve() {
    vector<vector<ll>> _h(N);
    int mx_sz = 0;
    for(int i = 0; i < N; ++i) {
        if(A[i].size() > mx_sz) mx_sz = A[i].size();
        _h[i].resize(A[i].size());
        for(int j = 0; j < A[i].size(); ++j) _h[i][j] = ((j ? _h[i][j - 1] : 0ll) * base1 + A[i][j]) % MOD;
        //for(int j = 0; j < A[i].size(); ++j) cout << _h[i][j] << " "; cout << "\n";
    }
    vector<ll> pw(mx_sz); pw[0] = 1; pw[1] = base1;
    for(int i = 2; i < pw.size(); ++i) pw[i] = pw[i - 1] * pw[1] % MOD;
    for(int i = 0; i < M; ++i) {
        ll res = 0;
        ll valP = 0, valQ = 0;
        for(int j = 0; j < P[i].size(); ++j) valP = (valP * base1 + P[i][j]) % MOD;
        for(int j = 0; j < Q[i].size(); ++j) valQ = (valQ * base1 + Q[i][j]) % MOD;
        //cout << valP << " " << valQ << "\n";
        for(int j = 0; j < N; ++j) {
            if(P[i].size() > A[j].size() || Q[i].size() > A[j].size()) continue;
            if(valP == _h[j][P[i].size() - 1] &&
            ((Q[i].size() == A[j].size() && valQ == _h[j].back()) ||
             (_h[j].back() - (_h[j][A[j].size() - Q[i].size() - 1]) * pw[Q[i].size()] % MOD + MOD) % MOD == valQ)) ++res;
        }
        cout << res << "\n";
    }
}
struct node {
    vector<int> flag;
    int nxt[26];
    node() { memset(nxt, -1, sizeof(nxt)); }
};
void dfs(vector<node>& trie, vector<int>& LID, vector<int>& RID, vector<int>& V, int& tot, int u) {
    V[LID[u] = tot++] = u;
    for(auto v : trie[u].nxt) if(v != -1) dfs(trie, LID, RID, V, tot, v);
    RID[u] = tot;
}
void solve1() {
    vector<node> t1, t2; t1.emplace_back(); t2.emplace_back();
    for(int i = 0; i < N; ++i) {
        int temp = 0;
        for(int j = 0; j < A[i].size(); ++j) {
            if(t1[temp].nxt[A[i][j] - 'A'] != -1) temp = t1[temp].nxt[A[i][j] - 'A'];
            else {
                temp = t1[temp].nxt[A[i][j] - 'A'] = t1.size();
                t1.emplace_back();
            }
        }
        t1[temp].flag.emplace_back(i);
        temp = 0;
        for(int j = A[i].size() - 1; ~j; --j) {
            if(t2[temp].nxt[A[i][j] - 'A'] != -1) temp = t2[temp].nxt[A[i][j] - 'A'];
            else {
                temp = t2[temp].nxt[A[i][j] - 'A'] = t2.size();
                t2.emplace_back();
            }
        }
        t2[temp].flag.emplace_back(i);
    }
    for(int i = 0; i < M; ++i) {
        int temp = 0;
        for(int j = 0; j < P[i].size(); ++j) {
            if(t1[temp].nxt[P[i][j] - 'A'] != -1) temp = t1[temp].nxt[P[i][j] - 'A'];
            else {
                temp = t1[temp].nxt[P[i][j] - 'A'] = t1.size();
                t1.emplace_back();
            }
        }
        temp = 0;
        for(int j = Q[i].size() - 1; ~j; --j) {
            if(t2[temp].nxt[Q[i][j] - 'A'] != -1) temp = t2[temp].nxt[Q[i][j] - 'A'];
            else {
                temp = t2[temp].nxt[Q[i][j] - 'A'] = t2.size();
                t2.emplace_back();
            }
        }
    }
    vector<int> LID1(t1.size()), RID1(t1.size()), LID2(t2.size()), RID2(t2.size()), V1(t1.size()), V2(t2.size()), prv1(t1.size() + 1), prv2(t2.size() + 1);
    int tot = 0; dfs(t1, LID1, RID1, V1, tot, 0);
    tot = 0; dfs(t2, LID2, RID2, V2, tot, 0);
    prv1[0] = prv2[0] = -1;
    for(int i = 1; i <= t1.size(); ++i) {
        if(t1[V1[i - 1]].flag.size()) prv1[i] = i - 1;
        else prv1[i] = prv1[i - 1];
    }
    for(int i = 1; i <= t2.size(); ++i) {
        if(t2[V2[i - 1]].flag.size()) prv2[i] = i - 1;
        else prv2[i] = prv2[i - 1];
    }
    vector<int> turn(N, -1);
    for(int i = 0; i < M; ++i) {
        int id1 = 0, id2 = 0, res = 0;
        for(int j = 0; j < P[i].size(); ++j) id1 = t1[id1].nxt[P[i][j] - 'A'];
        for(int reach = prv1[RID1[id1]]; reach >= LID1[id1]; reach = prv1[reach]) {
            for(const auto& v : t1[V1[reach]].flag) turn[v] = i;
        }
        //continue;
        for(int j = Q[i].size() - 1; ~j; --j) id2 = t2[id2].nxt[Q[i][j] - 'A'];
        for(int reach = prv2[RID2[id2]]; reach >= LID2[id2]; reach = prv2[reach]) {
            //cout << "ASK: " << t2[V2[reach]].flag << " ";
            for(const auto& v : t2[V2[reach]].flag) if(turn[v] == i) ++res;
        }   
        cout << res << "\n";
    }
}
};
void solve() {
    cin >> N >> M;
    for(int i = 0; i < N; ++i) cin >> A[i];
    for(int i = 0; i < M; ++i) cin >> P[i] >> Q[i];
    //if(sub1::check()) return sub1::solve();
    if(sub2::check()) return sub2::solve1();
    assert(false);
}
// T - S(i) = j
// T - S(j) = i
// S(j) - S(i) = j - i
// <=> S(j) - j = S(i) - i
int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    int t = 1;
    //cin >> t;
    while(t--) solve();
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...