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 pref, l, r, id, tp;
- };
- 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, tt;
- int n;
- string t, s;
- 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);
- }
- bool cmp(node a, node b) {
- return a.pref < b.pref;
- }
- void update(int pos, int val) {
- while(pos <= n) {
- tt[pos] += val;
- pos = (pos | (pos - 1)) + 1;
- }
- }
- int get(int pos) {
- int ans = 0;
- while(pos > 0) {
- ans += tt[pos];
- pos = (pos & (pos - 1));
- }
- return ans;
- }
- 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;
- }
- tt.resize(MAXN);
- vector<node> rq;
- int q;
- cin >> q;
- vi ans(q);
- for(int i = 0; i < q; i++) {
- int l, r, l1, r1;
- cin >> l >> r >> l1 >> r1;
- l--;
- r--;
- l1--;
- r1--;
- if(r - l > r1 - l1) {
- ans[i] = 0;
- continue;
- }
- if(n == 1) {
- if(r == l) {
- if(t[l] == s[l1]) {
- ans[i] = 1;
- }
- else {
- ans[i] = 0;
- }
- }
- else {
- ans[i] = 0;
- }
- 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;
- }
- }
- resRight = tl;
- tl = -1, tr = rp[dn + l];
- while(tr - tl > 1) {
- int mid = (tl + tr) >> 1;
- int suf = p[mid];
- if(n - suf < r - l + 1) {
- tl = mid;
- }
- else if(compare(l, r, suf, suf + r - l)) {
- tr = mid;
- }
- else {
- tl = mid;
- }
- }
- resLeft = tr;
- resRight++;
- rq.pb({resLeft, l1, r1 - r + l, i, -1});
- rq.pb({resRight, l1, r1 - r + l, i, 1});
- // int pr1 = get(roots[resRight], 0, n, l1, r1 - r + l);
- // int pr2 = get(roots[resLeft - 1], 0, n, l1, r1 - r + l);
- // writeInt(pr1 - pr2);
- // writeChar('\n');
- }
- sort(all(rq), cmp);
- int cur_ver = 0;
- for(int i = 0; i < rq.size(); i++) {
- // cerr << rq[i].pref << " " << rq[i].l << " " << rq[i].r << " " << rq[i].id << '\n';
- while(cur_ver < rq[i].pref) {
- cur_ver++;
- // cerr << p[cur_ver - 1] << " +1 " << '\n';
- update(p[cur_ver - 1] + 1, 1);
- }
- ans[rq[i].id] += rq[i].tp * (get(rq[i].r + 1) - get(rq[i].l));
- }
- for(auto i : ans) {
- cout << i << '\n';
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement