Submission #1132026

#TimeUsernameProblemLanguageResultExecution timeMemory
1132026snowmelSelling RNA Strands (JOI16_selling_rna)C++20
60 / 100
280 ms45192 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"; } } }; namespace sub3 { bool check() { int sum1 = 0, sum2 = 0; for(int i = 0; i < N; ++i) sum1 += A[i].size(); if(sum1 > int(1e5)) return false; sum1 = 0; for(int i = 0; i < M; ++i) { sum1 += P[i].size(); sum2 += Q[i].size(); } return max(sum1, sum2) <= int(1e5); } struct node { int nxt[26], conv = -1; vector<int> pos; node() { memset(nxt, -1, sizeof(nxt)); } } trie1[maxN]; struct node2 { int nxt[26], cnt = 0; node2() { memset(nxt, -1, sizeof(nxt)); } }; int prv[maxN << 2], LID[maxN << 2], RID[maxN << 2], V[maxN << 2]; void dfs1(int& tot, int u = 0) { V[LID[u] = tot++] = u; for(const auto& v : trie1[u].nxt) if(v != -1) dfs1(tot, v); RID[u] = tot; } void dfs2(vector<node2>& trie2, vector<int>& cnt, int u) { while(cnt.size() <= u) cnt.emplace_back(); cnt[u] = trie2[u].cnt; for(const auto& v : trie2[u].nxt) { if(v != -1) { dfs2(trie2, cnt, v); cnt[u] += cnt[v]; } } } void solve() { trie1[0] = node(); int tot = 1; for(int i = 0, temp; i < N; ++i) { temp = 0; for(int j = 0; j < A[i].size(); ++j) { if(trie1[temp].nxt[A[i][j] - 'A'] != -1) temp = trie1[temp].nxt[A[i][j] - 'A']; else trie1[temp = trie1[temp].nxt[A[i][j] - 'A'] = tot++] = node(); } trie1[temp].pos.emplace_back(i); } { int sz = 0; dfs1(sz); } prv[0] = -1; for(int i = 1; i <= tot; ++i) prv[i] = (!trie1[V[i - 1]].pos.empty() ? i - 1 : prv[i - 1]); vector<int> cnt; vector<node2> trie2; trie2.reserve(tot * 400); cnt.reserve(tot * 400); for(int i = 0, id1 = 0, id2 = 0; i < M; ++i) { id1 = 0; for(int j = 0; j < P[i].size(); ++j) { id1 = trie1[id1].nxt[P[i][j] - 'A']; if(id1 == -1) break; } if(id1 == -1) { cout << "0\n"; continue; } if(trie1[id1].conv == -1) { trie1[id1].conv = trie2.size(); trie2.emplace_back(); for(int pid = prv[RID[id1]]; pid >= LID[id1]; pid = prv[pid]) { for(const auto& pos: trie1[V[pid]].pos) { id2 = trie1[id1].conv; for(int j = A[pos].size() - 1; ~j; --j) { if(trie2[id2].nxt[A[pos][j] - 'A'] != -1) id2 = trie2[id2].nxt[A[pos][j] - 'A']; else { id2 = trie2[id2].nxt[A[pos][j] - 'A'] = trie2.size(); trie2.emplace_back(); } } ++trie2[id2].cnt; } } dfs2(trie2, cnt, trie1[id1].conv); } id2 = trie1[id1].conv; for(int j = Q[i].size() - 1; ~j; --j) { id2 = trie2[id2].nxt[Q[i][j] - 'A']; if(id2 == -1) break; } if(id2 == -1) { cout << "0\n"; continue; } cout << cnt[id2] << "\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::solve(); if(sub3::check()) return sub3::solve(); assert(false); } // T - S(i) = j // T - S(j) = i // S(j) - S(i) = j - i // <=> S(j) - j = S(i) - i int main() { //freopen("INP.inp", "r", stdin); //freopen("OUT.out", "w", stdout); ios_base::sync_with_stdio(0); cin.tie(0); int t = 1; //cin >> t; while(t--) { //string randomS; cin >> randomS; cout << randomS << "\n"; solve(); } } /* 12440 12410 12410 0 25150 25150 25150 12410 25150 25150 25150 25 */
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...