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
- }
- template <class T = int> inline T readInt();
- inline double readDouble();
- inline int readUInt();
- inline int readChar(); // first non-blank character
- inline void readWord( char *s );
- inline bool readLine( char *s ); // do not save '\n'
- inline bool isEof();
- inline int getChar();
- inline int peekChar();
- inline bool seekEof();
- inline void skipBlanks();
- template <class T> inline void writeInt( T x, char end = 0, int len = -1 );
- inline void writeChar( int x );
- inline void writeWord( const char *s );
- inline void writeDouble( double x, int len = 0 );
- inline void flush();
- static struct buffer_flusher_t {
- ~buffer_flusher_t() {
- flush();
- }
- } buffer_flusher;
- /** Read */
- static const int buf_size = 4096;
- static unsigned char buf[buf_size];
- static int buf_len = 0, buf_pos = 0;
- inline bool isEof() {
- if (buf_pos == buf_len) {
- buf_pos = 0, buf_len = fread(buf, 1, buf_size, stdin);
- if (buf_pos == buf_len)
- return 1;
- }
- return 0;
- }
- inline int getChar() {
- return isEof() ? -1 : buf[buf_pos++];
- }
- inline int peekChar() {
- return isEof() ? -1 : buf[buf_pos];
- }
- inline bool seekEof() {
- int c;
- while ((c = peekChar()) != -1 && c <= 32)
- buf_pos++;
- return c == -1;
- }
- inline void skipBlanks() {
- while (!isEof() && buf[buf_pos] <= 32U)
- buf_pos++;
- }
- inline int readChar() {
- int c = getChar();
- while (c != -1 && c <= 32)
- c = getChar();
- return c;
- }
- inline int readUInt() {
- int c = readChar(), x = 0;
- while ('0' <= c && c <= '9')
- x = x * 10 + c - '0', c = getChar();
- return x;
- }
- template <class T>
- inline T readInt() {
- int s = 1, c = readChar();
- T x = 0;
- if (c == '-')
- s = -1, c = getChar();
- else if (c == '+')
- c = getChar();
- while ('0' <= c && c <= '9')
- x = x * 10 + c - '0', c = getChar();
- return s == 1 ? x : -x;
- }
- inline double readDouble() {
- int s = 1, c = readChar();
- double x = 0;
- if (c == '-')
- s = -1, c = getChar();
- while ('0' <= c && c <= '9')
- x = x * 10 + c - '0', c = getChar();
- if (c == '.') {
- c = getChar();
- double coef = 1;
- while ('0' <= c && c <= '9')
- x += (c - '0') * (coef *= 1e-1), c = getChar();
- }
- return s == 1 ? x : -x;
- }
- inline void readWord( char *s ) {
- int c = readChar();
- while (c > 32)
- *s++ = c, c = getChar();
- *s = 0;
- }
- inline bool readLine( char *s ) {
- int c = getChar();
- while (c != '\n' && c != -1)
- *s++ = c, c = getChar();
- *s = 0;
- return c != -1;
- }
- /** Write */
- static int write_buf_pos = 0;
- static char write_buf[buf_size];
- inline void writeChar( int x ) {
- if (write_buf_pos == buf_size)
- fwrite(write_buf, 1, buf_size, stdout), write_buf_pos = 0;
- write_buf[write_buf_pos++] = x;
- }
- inline void flush() {
- if (write_buf_pos)
- fwrite(write_buf, 1, write_buf_pos, stdout), write_buf_pos = 0;
- }
- template <class T>
- inline void writeInt( T x, char end, int output_len ) {
- if (x < 0)
- writeChar('-'), x = -x;
- char s[24];
- int n = 0;
- while (x || !n)
- s[n++] = '0' + x % 10, x /= 10;
- while (n < output_len)
- s[n++] = '0';
- while (n--)
- writeChar(s[n]);
- if (end)
- writeChar(end);
- }
- inline void writeWord( const char *s ) {
- while (*s)
- writeChar(*s++);
- }
- inline void writeDouble( double x, int output_len ) {
- if (x < 0)
- writeChar('-'), x = -x;
- int t = (int)x;
- writeInt(t), x -= t;
- writeChar('.');
- for (int i = output_len - 1; i > 0; i--) {
- x *= 10;
- t = std::min(9ll, (int)x);
- writeChar('0' + t), x -= t;
- }
- x *= 10;
- t = std::min(9ll, (int)(x + 0.5));
- writeChar('0' + t);
- }
- 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;
- const int BASE2 = 43;
- const int MOD2 = 998244353ll;
- vi p(MAXN), cnt(MAXN), c(MAXN);
- vi pn(MAXN), cn(MAXN);
- vi h, ht, h2, ht2;
- vi pows, pows2;
- 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;
- }
- vi get_hash2(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] * pows2[i - 1]) % MOD2;
- }
- return ans;
- }
- int subhash(int l, int r, vi &h) {
- return (((h[r + 1] - h[l] + MOD) % MOD) * pows[n - l - 1]) % MOD;
- }
- int subhash2(int l, int r, vi &h) {
- return (((h[r + 1] - h[l] + MOD2) % MOD2) * pows2[n - l - 1]) % MOD2;
- }
- bool compare2(int l1, int r1, int l2, int r2) {
- return subhash2(l1, r1, ht2) == subhash2(l2, r2, h2);
- }
- bool compare(int l1, int r1, int l2, int r2) {
- return subhash(l1, r1, ht) == subhash(l2, r2, h) && (subhash(l1, r1, ht) == subhash(l2, r2, h)) == compare2(l1, r1, l2, r2);
- }
- 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;
- pows2.resize(mx);
- pows2[0] = 1;
- for(int i = 1; i < mx; i++) {
- pows[i] = pows[i - 1] * BASE;
- pows[i] %= MOD;
- pows2[i] = pows2[i - 1] * BASE2;
- pows2[i] %= MOD2;
- }
- h = get_hash(s);
- ht = get_hash(t);
- h2 = get_hash2(s);
- ht2 = get_hash2(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) {
- writeWord("0\n");
- continue;
- }
- if(n == 1) {
- if(r == l) {
- if(t[l] == s[l1]) {
- writeWord("1\n");
- }
- else {
- writeWord("0\n");
- }
- }
- else {
- writeWord("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;
- writeInt(pr1 - pr2);
- writeChar('\n');
- // cout << pr1 - pr2 << '\n';
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement