板子求调/kel
查看原帖
板子求调/kel
761491
Zzzcr楼主2024/5/1 09:55

RT,wa on #2

// Problem: Forensic Examination
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/CF666E
// Memory Limit: 750 MB
// Time Limit: 6000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt")

#include <bits/stdc++.h>
using namespace std;

#define _f(i, a, b) for (int i = a; i <= b; ++i)
#define _d(i, a, b) for (int i = a; i >= b; --i)
using pii = pair<int, int>;
using ll = long long;
#define fi first
#define se second

static constexpr int N = 5e5 + 5, M = 5e4 + 5, V = 4e7 + 5;

char s[N], tt[N];
int n, m, l;
int ls[V], rs[V], mx[V], res[V], rt[N << 1], cnt;
int sz = 1, len[N], ff[23][N << 1], rpos[N];

vector<char> t[M];
vector<int> G[N << 1];

struct state {
	int len, link;
	map<char, int> nxt;
} st[N << 1];

void pushup(int p) {
	if(mx[ls[p]] >= mx[rs[p]]) mx[p] = mx[ls[p]], res[p] = res[ls[p]];
	else mx[p] = mx[rs[p]], res[p] = res[rs[p]];
}

int add(int p, int x, int l = 1, int r = n) {
	if(!p) p = ++cnt;
	if(l == r) return mx[p]++, res[p] = l, p;
	int mid = (l + r) >> 1;
	if(x <= mid) ls[p] = add(ls[p], x, l, mid);
	else rs[p] = add(rs[p], x, mid + 1, r);
	pushup(p);
	return p;
}

int merge(int a, int b, int l = 1, int r = n) {
	if(!a || !b) return a + b;
	int root = ++cnt, mid = (l + r) >> 1;
	if(l == r) {
		mx[root] = mx[a] + mx[b], res[root] = l;
		return root;
	}
	ls[root] = merge(ls[a], ls[b], l, mid);
	rs[root] = merge(rs[a], rs[b], mid + 1, r);
	pushup(root);
	return root;
}

pii query(int p, int x, int y, int l = 1, int r = n) {
	if(!p) return {0, 0};
	if(x <= l && r <= y) return {res[p], mx[p]};
	int mid = (l + r) >> 1;
	pii lft = query(ls[p], x, y, l, mid);
	pii rgt = query(rs[p], x, y, mid + 1, r);
	return lft.se >= rgt.se ? lft : rgt;
}

int extend(int p, char c) {
	if(st[p].nxt.count(c)) {
		int q = st[p].nxt[c];
		if(st[q].len == st[p].len + 1) return q;
		else {
			int clone = ++sz;
			st[clone] = st[q], st[clone].len = st[p].len + 1, st[q].link = clone;
			while(p && st[p].nxt[c] == q) st[p].nxt[c] = clone, p = st[p].link;
			return clone;
		}
	}
	int cur = ++sz;
	st[cur].len = st[p].len + 1;
	while(p && !st[p].nxt.count(c)) st[p].nxt[c] = cur, p = st[p].link;
	if(!p) st[cur].link = 1;
	else {
		int q = st[p].nxt[c];
		if(st[q].len == st[p].len + 1) st[cur].link = q;
		else {
			int clone = ++sz;
			st[clone] = st[q], st[clone].len = st[p].len + 1;
			st[q].link = st[cur].link = clone;
			while(p && st[p].nxt[c] == q) st[p].nxt[c] = clone, p = st[p].link;
		}
	}
	return cur;
}

void dfs(int x, int f) {
	ff[0][x] = f;
	_f(i, 1, 21) ff[i][x] = ff[i - 1][ff[i - 1][x]];
	for(int v : G[x]) {
		if(v == f) continue;
		dfs(v, x);
		rt[x] = merge(rt[x], rt[v]);
	}
}

void solve() {
	cin >> (s + 1) >> n, l = strlen(s + 1);
	_f(i, 1, n) {
		cin >> (tt + 1);
		int lst = 1, ll = strlen(tt + 1);
		_f(j, 1, ll)
			t[i].emplace_back(tt[j]), lst = extend(lst, tt[j]);
	}
	_f(i, 1, n) {
		int lst = 1;
		for(char v : t[i])
			lst = st[lst].nxt[v], rt[lst] = add(rt[lst], i);
	}
	int nowlen = 0, p = 1;
	_f(i, 1, l) {
		while(p && !st[p].nxt.count(s[i])) p = st[p].link, nowlen = st[p].len;
		if(!p) nowlen = 0, p = 1;
		else p = st[p].nxt[s[i]], ++nowlen;
		len[i] = nowlen, rpos[i] = p;
	}
	_f(i, 2, sz) G[st[i].link].emplace_back(i);
	dfs(1, 0);
	cin >> m;
	while(m--) {
		int l, r, pl, pr, sl, p;
		cin >> l >> r >> pl >> pr, sl = pr - pl + 1, p = rpos[pr];
		if(len[pr] < sl) {
			cout << l << ' ' << 0 << '\n';
			continue;
		}
		_d(i, 21, 0) {
			int j = ff[i][p];
			if(st[st[j].link].len + 1 >= sl) p = j;
		}
		pii ret = query(rt[p], l, r);
		if(ret.se == 0) ret.fi = l;
		cout << ret.fi << ' ' << ret.se << '\n';
	}
}

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);

	solve();
	return 0;
}

// by zzzcr.

2024/5/1 09:55
加载中...