Solutions of String occurences 3 - MarisaOJ: Marisa Online Judge

Solutions of String occurences 3

Select solution language

Write solution here.


User Avatar kh0i    Created at    7 likes

Ta sẽ xử lí các truy vấn có cùng độ dài cùng một lúc bằng cách sử dụng Hash. Nhận thấy rằng $\sum |T| \le 10^5$, nên ta chỉ cần xử lí tối đa $\sqrt{2 \cdot |T|}$ độ dài khác nhau của các truy vấn. *Chứng minh:* $\displaystyle 1 + 2 + \dots + \sqrt{2 \cdot |T|} = \frac{\sqrt{2 \cdot |T|}(\sqrt{2 \cdot |T|} + 1)}{2} = \frac{2 \cdot |T| + \sqrt{2 \cdot |T|}}{2} \lt |T|$ Với mỗi độ dài, ta có thể sort các hash của các xâu con liên tiếp, sau đó dùng two pointers để đếm số lượng xâu con thỏa mãn. Độ phức tạp: $O(\sqrt{(2 \cdot |T|)} * |S| + q * \log q)$. Code mẫu: ```cpp #include "bits/stdc++.h" using namespace std; #define F first #define S second #define sz(x) int((x).size()) using ll = long long; mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count()); ll get_rand(ll l, ll r) { assert(l <= r); return uniform_int_distribution<ll> (l, r)(rng); } #ifdef LOCAL #include "debug.h" #else #define debug(...) #endif const int N = 1e5 + 3; struct Hash{ const ll base = 31; const ll MOD = 1e9 + 3; int n; string s; vector<ll> p, hash; void precalc(int _n){ p[0] = 1; for(int i = 1; i <= _n; ++i) p[i] = (p[i - 1] * base) % MOD; } void init(string x){ n = x.size(); hash.resize(n + 2, 0); p.resize(n + 2, 0); precalc(n); s = ' ' + x; for(int i = 1; i <= n; ++i) hash[i] = (hash[i - 1] * base + (s[i] - 'a' + 1)) % MOD; } ll get_hash(int l, int r){ return (hash[r] - hash[l - 1] * p[r - l + 1] + MOD * MOD) % MOD; } ll get_single_hash(string x){ ll res = 0; for(int i = 0; i < sz(x); ++i) res = (res * base + (x[i] - 'a' + 1)) % MOD; return res; } } mim; int n, ans[N], m; string s; vector<pair<ll, int>> q[N]; void solve(){ cin >> s; mim.init(s); n = sz(s); s = ' ' + s; cin >> m; for(int i = 1; i <= m; ++i){ string t; cin >> t; q[sz(t)].push_back({mim.get_single_hash(t), i}); } for(int i = 1; i <= n; ++i){ if(sz(q[i])){ vector<ll> v; for(int k = i; k <= n; ++k) v.push_back(mim.get_hash(k - i + 1, k)); sort(v.begin(), v.end()); sort(q[i].begin(), q[i].end()); int cur = -1, cnt = 0; for(auto [hsh, id] : q[i]){ while(cur + 1 < sz(v) and v[cur + 1] <= hsh){ ++cur; cnt = (cur == 0 ? 1 : (v[cur] == v[cur - 1] ? cnt + 1 : 1)); } ans[id] = (cur >= 0 and hsh == v[cur] ? cnt : 0); } } } for(int i = 1; i <= m; ++i) cout << ans[i] << '\n'; } int32_t main() { cin.tie(nullptr)->sync_with_stdio(0); int test = 1; // cin >> test; for(int i = 1; i <= test; ++i){ // cout << "Case #" << i << ": "; solve(); } cerr << "\nTime elapsed: " << 1000.0 * clock() / CLOCKS_PER_SEC << " ms.\n"; return 0; } ```