Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- using namespace std;
- #define sim template < class c
- #define ris return * this
- #define dor > debug & operator <<
- #define eni(x) sim > typename \
- enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
- sim > struct rge { c b, e; };
- sim > rge<c> range(c i, c j) { return rge<c>{i, j}; }
- sim > auto dud(c* x) -> decltype(cerr << *x, 0);
- sim > char dud(...);
- struct debug {
- #ifdef LOCAL
- ~debug() { cerr << endl; }
- eni(!=) cerr << boolalpha << i; ris; }
- eni(==) ris << range(begin(i), end(i)); }
- sim, class b dor(pair < b, c > d) {
- ris << "(" << d.first << ", " << d.second << ")";
- }
- sim dor(rge<c> d) {
- *this << "[";
- for (auto it = d.b; it != d.e; ++it)
- *this << ", " + 2 * (it == d.b) << *it;
- ris << "]";
- }
- #else
- sim dor(const c&) { ris; }
- #endif
- };
- #define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "
- // debug & operator << (debug & dd, P p) { dd << "(" << p.x << ", " << p.y << ")"; return dd; }
- // ALCS, https://www.sciencedirect.com/science/article/pii/S0166218X07002727
- vector<vector<int>> get_ih(string a, string b) {
- int na = a.length();
- int nb = b.length();
- vector<vector<int>> ih(na + 1, vector<int>(nb + 1));
- auto iv = ih;
- for(int j = 0; j <= nb; ++j) {
- ih[0][j] = j;
- }
- for(int l = 0; l <= na; ++l) {
- iv[l][0] = 0;
- }
- for(int l = 1; l <= na; ++l) {
- for(int j = 1; j <= nb; ++j) {
- if(a[l-1] != b[j-1]) {
- ih[l][j] = max(iv[l][j-1], ih[l-1][j]);
- iv[l][j] = min(iv[l][j-1], ih[l-1][j]);
- }
- else {
- ih[l][j] = iv[l][j-1];
- iv[l][j] = ih[l-1][j];
- }
- }
- }
- return ih;
- }
- int one[3005], two[3005];
- int last_size;
- void get_row(int A, int b_high, const vector<vector<int>>& ih, int ans[]) {
- // a[0..A] with b[low..]
- A++;
- b_high++;
- for(int i = 0; i <= b_high; ++i) {
- ans[i] = 0;
- }
- for(int j = 1; j <= b_high; ++j) {
- int L = ih[A][j];
- int R = j - 1;
- if(L <= R) {
- ans[L]++;
- if(R + 1 < b_high) {
- ans[R+1]--;
- }
- // for(int i = L; i <= R; ++i) {
- // ans[i]++;
- // }
- }
- // in[A][j] .. j - 1
- }
- for(int i = 1; i < b_high; ++i) {
- ans[i] += ans[i-1];
- }
- /*for(int b_low = 0; b_low < b_high; ++b_low) {
- int pref = 0;
- for(int j = b_low + 1; j <= b_high; ++j) {
- if(b_low >= ih[A][j]) {
- pref++;
- }
- }
- ans.push_back(pref);
- }*/
- ans[b_high] = 0;
- last_size = b_high + 1;
- reverse(ans, ans + last_size);
- // reverse(ans.begin(), ans.end());
- // return ans;
- // return answer;
- };
- string read() {
- static char s[3005];
- scanf("%s", s);
- return string(s);
- }
- struct Query {
- int la, ra, lb, rb, id;
- void read(int _id) {
- id = _id;
- scanf("%d%d%d%d", &la, &ra, &lb, &rb);
- la--; ra--; lb--; rb--;
- }
- };
- vector<int> print;
- void rec_solve(string a, string b, vector<Query>& queries) {
- if(/*(int) a.length() < 5 && */ queries.empty()) {
- return;
- }
- if(a.length() < b.length()) {
- swap(a, b);
- for(Query& query : queries) {
- swap(query.la, query.lb);
- swap(query.ra, query.rb);
- }
- }
- int na = a.length();
- int nb = b.length();
- const int mid = na / 2;
- string a_left = a.substr(0, mid);
- string a_right = a.substr(mid);
- // debug() << imie(a_left) imie(a_right);
- vector<vector<int>> ih_right = get_ih(a_right, b);
- reverse(a_left.begin(), a_left.end());
- reverse(b.begin(), b.end());
- vector<vector<int>> ih_left = get_ih(a_left, b);
- // vector<vector<int>> ih_right = get_ih(a_right, b);
- reverse(a_left.begin(), a_left.end());
- reverse(b.begin(), b.end());
- vector<Query> left_queries, right_queries;
- for(Query query : queries) {
- int la = query.la, ra = query.ra, lb = query.lb, rb = query.rb;
- if((ra - la + 1) * (rb - lb + 1) <= 1000 || (int) queries.size() <= 10) {
- int len_a = ra - la + 1;
- int len_b = rb - lb + 1;
- vector<int> dp(len_b + 1);
- for(int i = 0; i < len_a; ++i) {
- for(int j = len_b - 1; j >= 0; --j) {
- if(a[la+i] == b[lb+j]) {
- dp[j+1] = dp[j] + 1;
- }
- }
- for(int j = 0; j < len_b; ++j) {
- dp[j+1] = max(dp[j+1], dp[j]);
- }
- }
- print[query.id] = dp.back();
- continue;
- }
- if(ra < mid) {
- left_queries.push_back(query);
- continue;
- }
- if(la >= mid) {
- query.la -= mid;
- query.ra -= mid;
- right_queries.push_back(query);
- continue;
- }
- // if(la < mid && ra >= mid) {
- get_row(mid - 1 - la, nb - 1 - lb, ih_left, one);
- int one_size = last_size;
- get_row(ra - mid, rb, ih_right, two);
- int two_size = last_size;
- // debug() << imie(one) imie(two);
- int answer = 0;
- for(int i = 0; i < one_size; ++i) {
- int j = rb-lb+1 - i;
- if(0 <= j && j < two_size) {
- answer = max(answer, one[i] + two[j]);
- }
- }
- print[query.id] = answer;
- // printf("%d\n", answer);
- // }
- /*
- else { // brute force
- assert(false);
- // puts("?");
- // continue;
- vector<vector<int>> ih = get_ih(a.substr(la), b);
- int A = ra - la;
- int b_low = lb, b_high = rb;
- // a[0..A] with b[low..]
- A++;
- b_high++;
- int answer = 0;
- for(int j = b_low + 1; j <= b_high; ++j) {
- if(b_low >= ih[A][j]) {
- answer++;
- }
- }
- print[query.id] = answer;
- // printf("%d\n", answer);
- }*/
- }
- rec_solve(a_left, b, left_queries);
- rec_solve(a_right, b, right_queries);
- }
- int main() {
- // string a = "yxxyzyzx";
- // string b = "yxxyzxyzxyxzx";
- int na, nb, q;
- scanf("%d%d%d", &na, &nb, &q);
- string a = read();
- string b = read();
- vector<Query> queries(q);
- for(int i = 0; i < q; ++i) {
- queries[i].read(i);
- }
- print.resize(q, -1);
- rec_solve(a, b, queries);
- for(int x : print) {
- printf("%d\n", x);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment