Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- ┓┏┓┏┓┃
- ┛┗┛┗┛┃
- ┓┏┓┏┓┃
- ┛┗┛┗┛┃
- ┓┏┓┏┓┃\○/
- ┛┗┛┗┛┃ / /
- ┓┏┓┏┓┃ノ
- ┛┗┛┗┛┃
- ┓┏┓┏┓┃
- ┛┗┛┗┛┃
- ┓┏┓┏┓┃
- ┛┗┛┗┛┃
- ┓┏┓┏┓┃
- ┛┗┛┗┛┃
- ┓┏┓┏┓┃┓
- ┛┗┛┗┛┃┃
- MIPTCLASSICMIPTCLASSICMIPTCLASSICMIPTCLASSICMIPTCLASSICMIPTCLASSIC
- */
- // #define pragma
- #ifdef pragma
- #pragma GCC optimize("Ofast")
- #pragma GCC optimize("no-stack-protector")
- #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
- #pragma GCC optimize("unroll-loops")
- #pragma GCC diagnostic ignored "-Wunused-result"
- #endif // pragma
- #include<bits/stdc++.h>
- #include <ext/pb_ds/assoc_container.hpp>
- #include <ext/pb_ds/tree_policy.hpp>
- #define ll long long
- #define all(x) begin(x), end(x)
- #define pb push_back
- #define x first
- #define y second
- #define int long long
- #define zero(two) memset(two, 0, sizeof(two))
- using namespace std;
- using namespace __gnu_pbds;
- typedef vector<int> vi;
- typedef vector<bool> vb;
- typedef pair<int, int> pii;
- typedef long double ld;
- typedef vector<vi> matrix;
- template<typename T>
- using kawaii_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
- const ld PI = atan2(0, -1);
- void seriy() {
- ios::sync_with_stdio(0);
- cin.tie(0);
- cout.tie(0);
- cout << fixed << setprecision(10);
- #if 1
- freopen("input", "r", stdin);
- freopen("output", "w", stdout);
- #endif
- }
- struct node {
- int sum;
- node *left;
- node *right;
- };
- const int INF = 1e9 + 7;
- const int MAXN = 1e6 + 10;
- const int BASE = 47;
- const int MOD = 1e9 + 7;
- vi p(MAXN), cnt(MAXN), c(MAXN);
- vi pn(MAXN), cn(MAXN);
- vi h, ht;
- vi pows;
- int n;
- string t, s;
- void build(node *&v, int tl, int tr, int pos) {
- if(tl == tr) {
- if(tl == pos) v -> sum = 1;
- return;
- }
- int tm = (tl + tr) >> 1;
- v -> left = new node();
- v -> right = new node();
- build(v -> left, tl, tm, pos);
- build(v -> right, tm + 1, tr, pos);
- v -> sum = v -> left -> sum + v -> right -> sum;
- }
- int get(node *&v, int tl, int tr, int l, int r) {
- if(tl > r || tr < l) {
- return 0;
- }
- if(tl >= l && tr <= r) {
- return v -> sum;
- }
- int tm = (tl + tr) >> 1;
- int left = get(v -> left, tl, tm, l, r);
- int right = get(v -> right, tm + 1, tr, l, r);
- return left + right;
- }
- void update(node *&v, node *&v2, int tl, int tr, int pos) {
- // cerr << tl << " " << tr << '\n';
- if(tl > pos || tr < pos) {
- return;
- }
- if(tl == tr) {
- (v -> sum)++;
- // cerr << tl << " " << tr << " " << v -> sum << '\n';
- return;
- }
- int tm = (tl + tr) >> 1;
- if(pos > tm) {
- v -> left = v2 -> left;
- v -> right = new node();
- update(v -> right, v2 -> right, tm + 1, tr, pos);
- }
- else {
- v -> right = v2 -> right;
- v -> left = new node();
- update(v -> left, v2 -> left, tl, tm, pos);
- }
- v -> sum = v -> left -> sum + v -> right -> sum;
- // cerr << tl << " " << tr << " " << v -> sum << '\n';
- }
- vi get_hash(string s) {
- int n = s.size();
- vi ans(n + 1);
- for(int i = 1; i <= n; i++) {
- ans[i] = (ans[i - 1] + s[i - 1] * pows[i - 1]) % MOD;
- }
- return ans;
- }
- int subhash(int l, int r, vi &h) {
- return (((h[r + 1] - h[l] + MOD) % MOD) * pows[n - l - 1]) % MOD;
- }
- bool compare(int l1, int r1, int l2, int r2) {
- return subhash(l1, r1, ht) == subhash(l2, r2, h);
- }
- signed main() {
- seriy();
- cin >> t >> s;
- int dn = s.size();
- s += t;
- s += '$';
- n = s.size();
- int m = t.size();
- int mx = max(n, m);
- pows.resize(mx);
- pows[0] = 1;
- for(int i = 1; i < mx; i++) {
- pows[i] = pows[i - 1] * BASE;
- pows[i] %= MOD;
- }
- h = get_hash(s);
- ht = get_hash(t);
- for(int i = 0; i < n; i++) {
- cnt[s[i]]++;
- }
- for(int i = 1; i < MAXN; i++) {
- cnt[i] += cnt[i - 1];
- }
- for(int i = 0; i < n; i++) {
- p[--cnt[s[i]]] = i;
- }
- c[p[0]] = 0;
- int cur = 1;
- for(int i = 1; i < n; i++) {
- if (s[p[i]] != s[p[i - 1]]) {
- ++cur;
- }
- c[p[i]] = cur - 1;
- }
- for(int h = 0; (1 << h) < n; ++h) {
- for(int i = 0; i < n; i++) {
- pn[i] = (p[i] + n - (1 << h)) % n;
- }
- cnt.assign(MAXN, 0);
- for(int i = 0; i < n; i++) {
- cnt[c[pn[i]]]++;
- }
- for(int i = 1; i < cur; i++) {
- cnt[i] += cnt[i - 1];
- }
- for(int i = n - 1; i >= 0; i--) {
- p[--cnt[c[pn[i]]]] = pn[i];
- }
- cn[p[0]] = 0;
- cur = 1;
- for(int i = 1; i < n; i++) {
- int m1 = (p[i] + (1 << h)) % n, m2 = (p[i - 1] + (1 << h)) % n;
- if (c[p[i]] != c[p[i - 1]] || c[m1] != c[m2]) {
- cur++;
- }
- cn[p[i]] = cur - 1;
- }
- c = cn;
- }
- n--;
- for(int i = 0; i < n; i++) {
- p[i] = p[i + 1];
- }
- vi rp(n);
- for(int i = 0; i < n; i++) {
- rp[p[i]] = i;
- }
- vector<node*> roots(n + 1);
- roots[0] = new node();
- build(roots[0], 0, n, -1);
- for(int i = 1; i <= n; i++) {
- roots[i] = new node();
- update(roots[i], roots[i - 1], 0, n, p[i - 1]);
- }
- // cerr << compare3(0, 1, p[0], 6);
- // cerr << "-------\n";
- int q;
- cin >> q;
- while(q--) {
- int l, r, l1, r1;
- cin >> l >> r >> l1 >> r1;
- l--;
- r--;
- l1--;
- r1--;
- if(r - l > r1 - l1) {
- cout << "0\n";
- continue;
- }
- if(n == 1) {
- if(r == l) {
- if(t[l] == s[l1]) {
- cout << "1\n";
- }
- else {
- cout << "0\n";
- }
- }
- else {
- cout << "0\n";
- }
- continue;
- }
- int resLeft, resRight;
- int tl = rp[dn + l], tr = n;
- while(tr - tl > 1) {
- int mid = (tr + tl) >> 1;
- int suf = p[mid];
- if(n - suf < r - l + 1) {
- tr = mid;
- }
- else if(compare(l, r, suf, suf + r - l)) {
- tl = mid;
- }
- else {
- tr = mid;
- }
- // cerr << mid << " !" << '\n';
- // cerr << mid << " " << compare2(l, r, suf, r1) << '\n';
- // cerr << "------\n";
- }
- resRight = tl;
- tl = -1, tr = rp[dn + l];
- // cerr << compare()
- while(tr - tl > 1) {
- int mid = (tl + tr) >> 1;
- int suf = p[mid];
- // cerr << mid << " ";
- if(n - suf < r - l + 1) {
- // cerr << "l\n";
- tl = mid;
- }
- else if(compare(l, r, suf, suf + r - l)) {
- // cerr << "r\n";
- tr = mid;
- }
- else {
- // cerr << "l\n";
- tl = mid;
- }
- // cerr << '\n';
- // cerr << mid << " !" << '\n';
- // cerr << mid << " " << compare3(l, r, suf, l1) << '\n';
- // cerr << "-----\n";
- }
- // cerr << '\n';
- resLeft = tr;
- // if(resLeft == resRight) {
- // cout << "0\n";
- // continue;
- // }
- // cerr << resLeft << " " << resRight << '\n';
- // assert(resRight >= resLeft);
- // cout << resRight - resLeft + 1 << '\n';
- resLeft++;
- resRight++;
- // assert(l1 <= r1 - r + l);
- int pr1 = get(roots[resRight], 0, n, l1, r1 - r + l);
- int pr2 = get(roots[resLeft - 1], 0, n, l1, r1 - r + l);
- // cerr << pr1 << " " << pr2 << '\n';
- // cerr << 1;
- cout << pr1 - pr2 << '\n';
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement