#include<bits/stdc++.h> usingnamespacestd; typedeflonglong ll; #define pii pair<int, int> #define mk make_pair #define ls tree[pos].l #define rs tree[pos].r constint N = 2e5 + 10; constint mod = 1e9 + 7;
constint SN = 2e5 + 100; int n; structseg { int l, r, sum; } tree[N * 20]; int scnt; voidpushup(int pos) { tree[pos].sum = tree[ls].sum + tree[rs].sum; } voidmodify(int &pos, int l, int r, int w) { if (!pos) pos = ++scnt; if (l == r) { tree[pos].sum++; return; }
int mid = (l + r) >> 1; if (w <= mid) modify(ls, l, mid, w); else modify(rs, mid + 1, r, w); pushup(pos); } intquery(int pos, int ql, int qr, int l, int r) { if (ql <= l && r <= qr) return tree[pos].sum; int mid = (l + r) >> 1; int res = 0; if (ql <= mid) res += query(ls, ql, qr, l, mid); if (qr > mid) res += query(rs, ql, qr, mid + 1, r); return res; }
intmerge(int u, int v, int l, int r) { if (!u || !v) return u + v; int pos = ++scnt; if (l == r) { tree[pos].sum = tree[u].sum + tree[v].sum; return pos; } int mid = (l + r) >> 1; ls = merge(tree[u].l, tree[v].l, l, mid); rs = merge(tree[u].r, tree[v].r, mid + 1, r); pushup(pos); return pos; }
int rt[SN]; structSAM { int trans[SN][26]; int mxl[SN], link[SN], pre, scnt; SAM() { pre = scnt = 1; }; voidinit() { for (int j = 1; j <= scnt; j++) { link[j] = 0; mxl[j] = 0; //siz[j] = 0; memset(trans[j], 0, sizeof(trans[j])); } scnt = pre = 1; }; voidinsert(int id, int p) { int cur = ++scnt; mxl[cur] = mxl[pre] + 1; int u; modify(rt[cur], 1, n, p); for (u = pre; u && !trans[u][id]; u = link[u]) trans[u][id] = cur; pre = cur; if (!u) link[cur] = 1; else { int x = trans[u][id]; if (mxl[x] == mxl[u] + 1) link[cur] = x; else { int nc = ++scnt; link[nc] = link[x]; mxl[nc] = mxl[u] + 1; memcpy(trans[nc], trans[x], sizeof(trans[x]));
link[cur] = link[x] = nc; for (; u && trans[u][id] == x; u = link[u]) trans[u][id] = nc; } } } } sam;
structedge { int to, nxt; } e[SN]; int ecnt, head[SN], f[SN][21]; voidaddadge(int u, int v) { e[++ecnt].to = v; e[ecnt].nxt = head[u]; head[u] = ecnt; } voiddfs(int x) { for (int i = 1; i <= 20; i++) f[x][i] = f[f[x][i - 1]][i - 1]; for (int i = head[x]; i; i = e[i].nxt) {
int to = e[i].to; f[to][0] = x; dfs(to); rt[x] = merge(rt[x], rt[to], 1, n); } }
char s[N]; int ed[N]; int m;
boolcheck(int l, int r, int ll, int rr, int x) { if (x == 0) return1; int u = ed[ll + x - 1]; //cout << u << endl; for (int i = 20; i >= 0; i--) if (f[u][i] && sam.mxl[f[u][i]] >= x) u = f[u][i]; //cout << u << endl; return query(rt[u], l + x - 1, r, 1, n) > 0; } intmain() { scanf("%d%d", &n, &m); scanf("%s", s + 1); for (int i = 1; i <= n; i++) sam.insert(s[i] - 'a', i), ed[i] = sam.pre; for (int i = 2; i <= sam.scnt; i++) addadge(sam.link[i], i); ///out << sam.scnt << endl;
dfs(1);
while (m--) { int l1, r1, l2, r2; scanf("%d%d%d%d", &l1, &r1, &l2, &r2); int l = 0; int r = min(r2 - l2 + 1, r1 - l1 + 1); int ans = 0; // cout << "---" << endl; // cout << check(l1, r1, l2, r2, 0) << endl; while (l <= r) { //cout << l << " " << r << endl; int mid = (l + r) >> 1; if (check(l1, r1, l2, r2, mid)) { ans = mid; l = mid + 1; } else r = mid - 1; } printf("%d\n", ans); } }