WA40pts玄关求调,马蜂良好
查看原帖
WA40pts玄关求调,马蜂良好
488052
FLY_lai楼主2024/8/19 14:37
#include <bits/stdc++.h>

using namespace std;
const int N = 2e5 + 5, M = 1e7 + 5;

int n, q;
string s;
int pos[N];

struct SegmentTree { //动态开点线段树,用于维护每个SAM结点的endpos 
	int sz;
	int rt[N], ls[M], rs[M], val[M];
	
	void new_chd(int x) {
		if (ls[x] == 0) {
			ls[x] = ++sz;
			rs[x] = ++sz;
			val[ls[x]] = val[rs[x]] = 0;
		}
	}
	void pushup(int x) {
		val[x] = val[ls[x]] + val[rs[x]];
	}
	void mdf(int x, int lx, int rx, int p, int v) { //给位置p增加v 
		if (lx + 1 == rx) {
			val[x] += v;
			return ;
		}
		int m = (lx + rx) / 2;
		new_chd(x);
		if (p < m)
			mdf(ls[x], lx, m, p, v);
		else
			mdf(rs[x], m, rx, p, v);
		pushup(x);
	}
	int qry(int x, int lx, int rx, int l, int r) {
		if (l <= lx && rx <= r)
			return val[x];
		if (l >= rx || lx >= r)	
			return 0;
		int m = (lx + rx) / 2;
		new_chd(x);
		return qry(ls[x], lx, m, l, r) + qry(rs[x], m, rx, l, r);
	}
	int mrg(int L, int R, int lx, int rx) { //把R合并到L,返回合并后的根结点 
		if (L == 0 || R == 0)
			return L + R;
		if (lx + 1 == rx) {
			val[L] += val[R]; 
			return L;
		}
		int x = ++sz, m = (lx + rx) / 2;
		ls[x] = mrg(ls[L], ls[R], lx, m);
		rs[x] = mrg(rs[L], rs[R], m, rx);
		pushup(x);
		return x;
	}
} st;
struct Node {
	int e[26] = {};
	int lnk = 0, len = 0;
};
int pw[25] = {1}, lg[N];
int fa[25][N];
struct SAM {
	int cnt, lst, sz;
	vector<Node> a;
	vector<int> e[N];
	
	SAM() {
		cnt = lst = 1;
		sz = 0;
		a = vector<Node>(2);
	}
	int cd(char ch) {
		return ch - 'a';
	}
	void add(char ch) {
		int x = cd(ch), p = lst;
		a.push_back(Node());
		a[lst = ++cnt].len = ++sz;
		while (p != 1 && a[p].e[x] == 0)
			a[p].e[x] = lst, p = a[p].lnk;
		if (p == 1 && a[p].e[x] == 0) {
			a[p].e[x] = lst;
			a[lst].lnk = p;
		}
		else {
			int q = a[p].e[x];
			if (a[q].len == a[p].len + 1)
				a[lst].lnk = q;
			else {
				int q_new = ++cnt;
				a.push_back(a[q]);
				a[q_new].len = a[p].len + 1;
				a[q].lnk = a[lst].lnk = q_new;
				while (a[p].e[x] == q)
					a[p].e[x] = q_new, p = a[p].lnk;
			}
		}
	}
	void set_edge() {
//		cout << cnt << endl;
		for (int i = 2; i <= cnt; i++) {
//			cout << i << ':' << a[i].lnk << ' ';
			e[a[i].lnk].push_back(i);
		}
	}
	void dfs(int x) {
		for (int i = 1; i <= 20; i++)
			fa[i][x] = fa[i - 1][fa[i - 1][x]];
		for (auto i: e[x]) {
			dfs(i);
			fa[0][i] = x;
			st.rt[x] = st.mrg(st.rt[x], st.rt[i], 1, n + 1);
		}
	}
} t;
bool chk(int x, int a, int b, int c, int d) { //判断x长度是否对(a,b,c,d)可行 
	int now = pos[c + x - 1]; //先取出s[1~c+x-1]的结点
	//找到最上面的结点 
	for (int i = 20; i >= 0; i--)
		if (fa[i][now] != 0 && t.a[fa[i][now]].len >= x)
			now = fa[i][now];
	//判断是否有以 [a+x-1,b]结尾的 
	return st.qry(st.rt[now], 1, n + 1, a + x - 1, b + 1) > 0;
}


int main() {
//	freopen("1.in", "r", stdin);
//	freopen("1.out", "w", stdout);
	cin >> n >> q >> s;
	
	for (int i = 0; i < s.size(); i++) {
		t.add(s[i]);
		pos[i + 1] = t.lst;
	}
	t.set_edge();
	st.sz = t.cnt;
	for (int i = 1; i <= t.cnt; i++)
		st.rt[i] = i;
	for (int i = 0; i < s.size(); i++)
		st.mdf(st.rt[pos[i + 1]], 1, n + 1, i + 1, 1);
	t.dfs(1);
	
	for (int i = 1, a, b, c, d; i <= q; i++) {
		cin >> a >> b >> c >> d;
		int l = 0, r = min(b - a + 1, d - c + 1) + 1;
		while (r - l > 1) {
			int mid = (l + r) / 2;
//			cout << mid << ':' << chk(mid, a, b, c, d) << endl;
			if (chk(mid, a, b, c, d))
				l = mid;
			else
				r = mid;
		}
		cout << l << endl;
	}
	return 0;
} 
2024/8/19 14:37
加载中...