#include<bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
typedef std::pair<int, int> PII;
typedef std::pair<ll, ll> PLL;
typedef double db;
#define re _read
#define ALL(x) (x).begin(),(x).end()
#define SZ(v) ((int)v.size())
#define fi first
#define se second
#define pb push_back
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define endl "\n"
using namespace std;
mt19937 mrand(random_device{}());
int rnd(int x) { return mrand() % x;}
template <typename T> std::ostream &operator<<(std::ostream &out, const std::vector<T> &v) { out << "["; bool first = true; for (auto &&e : v) { if (first) { first = false;} else {out << ", ";} out << e; } return out << "]"; }
template <typename A, typename B> std::ostream &operator<<(std::ostream &out, const std::pair<A, B> &v) { return out << "(" << v.first << ", " << v.second << ")"; }
template <typename K> std::ostream &operator<<(std::ostream &out, const std::set<K> &s) { out << "{"; bool first = true; for (auto &&k : s) { if (first) { first = false; } else { out << ", "; } out << k; } return out << "}"; }
template <typename K, typename V> std::ostream &operator<<(std::ostream &out, const std::map<K, V> &m) { out << "{"; bool first = true; for (auto &&[k, v] : m) { if (first) { first = false; } else { out << ", "; } out << k << ": " << v; } return out << "}"; }
template <class T> vector<vector<T>> Vector(int n, int m) { return vector<vector<T>> (n, vector<T> (m, 0)); }
template <class T> vector<vector<vector<T>>> Vector(int i, int j, int k) { return vector<vector<vector<T>>> (i, vector<vector<T>>(j, vector<T>(k, 0))); }
template <typename T> void OUT(T* a, int l, int r) { for (int i = l; i <= r; i ++) cout << a[i] << " "; puts(""); }
template<class T>
inline void _read(T& x) {
static T ans;
static unsigned int c;
static bool p;
for (c = getchar(); c != '-' && (c < '0' || c > '9'); c = getchar());
if (c == '-') p = false, c = getchar(); else p = true;
for (ans = 0; c <= '9' && c >= '0'; c = getchar()) ans = ans * 10 + c - '0';
x = p ? ans : -ans;
}
#define RMQ
const int maxn = 1e6 + 10;
struct SA {
int n, sa[maxn], rk[maxn], id[maxn], cnt[maxn], height[maxn], px[maxn];
void get_sa(const char* s, int _n) {
n = _n;
int m = 300, p = 0;
for (int i = 0; i <= m; i++) cnt[i] = 0;
for (int i = 1; i <= n; i++) cnt[rk[i] = (int)s[i]] ++;
for (int i = 1; i <= m; i++) cnt[i] += cnt[i - 1];
for (int i = n; i >= 1; i--) sa[cnt[rk[i]]--] = i;
for (int w = 1; w <= n; w <<= 1, m = p, p = 0) {
for (int i = n - w + 1; i <= n; i++) id[++p] = i;
for (int i = 1; i <=n; i++)
if (sa[i] > w) id[++p] = sa[i] - w;
for (int i = 0; i <= m; i++) cnt[i] = 0;
for (int i = 1; i <=n; i++) ++ cnt[rk[i]], px[i] = rk[id[i]];
for (int i = 1; i <= m; i++) cnt[i] += cnt[i - 1];
for (int i = n; i >= 1; i--) sa[cnt[px[i]] -- ] = id[i];
for (int i = 1; i <= n; i++) swap(rk[i], id[i]);
rk[sa[1]] = p = 1;
for (int i = 2; i <= n; i++)
rk[sa[i]] = (id[sa[i]] == id[sa[i - 1]] && id[sa[i] + w] == id[sa[i - 1] + w] ? p : ++p);
if (p >= n) break;
}
}
void get_height(const char* s){
for (int i = 1, k = 0; i <= n; i++) {
if (k) -- k;
int j = sa[rk[i] - 1];
while (s[i + k] == s[j + k]) ++ k;
height[rk[i]] = k;
}
}
} sa;
const int N = 5e4 + 10, INF = 1e9;
vector<PII> tmp;
struct Chairman_Tree {
int node_cnt, root[N];
struct T {
int l, r;
int v;
}tr[N << 8];
int get_node() {
node_cnt++;
tr[node_cnt].l = tr[node_cnt].r = 0, tr[node_cnt].v = INF;
return node_cnt;
}
void pushup(T& rt) {
rt.v = min(tr[rt.l].v, tr[rt.r].v);
}
void build(int& u, int l, int r) {
u = get_node();
if (l == r) return ;
int mid = (l + r) >> 1;
build(tr[u].l, l, mid), build(tr[u].r, mid + 1, r);
}
void modify(int pre, int& u, int l, int r) {
if (tmp.empty() || tmp.back().first > r) return ;
assert(tmp.back().first >= l);
u = get_node();
tr[u].l = tr[pre].l, tr[u].r = tr[pre].r;
if (l == r) {
#ifdef ROSHIN
printf("l=%d v=%d\n", l, tmp.back().second);
#endif
tr[u].v = tmp.back().second;
tmp.pop_back();
return ;
}
int mid = (l + r) >> 1;
modify(tr[pre].l, tr[u].l, l, mid);
modify(tr[pre].r, tr[u].r, mid + 1, r);
pushup(tr[u]);
}
int query(int u, int l, int r, int ql, int qr) {
if (!u || r < ql || l > qr || ql > qr) return INF;
if (l >= ql && r <= qr) return tr[u].v;
int res = INF;
int mid = (l + r) >> 1;
res = query(tr[u].l, l, mid, ql, qr);
res = min(res, query(tr[u].r, mid + 1, r, ql, qr));
#ifdef ROSHIN
printf("l=%d, r=%d, res=%d\n", l, r, res);
#endif
return res;
}
}ctr;
char s[N];
int n, q;
PII H[N];
int p[N];
set<int> S[N];
int updated[N], cnt = 0, id[N];
int find(int x) {
if (x != p[x]) p[x] = find(p[x]);
return p[x];
}
void update(int pos, int val) {
if (!updated[pos]) id[cnt++] = pos;
updated[pos] = val;
}
void Union(int x, int y) {
x = find(x), y = find(y);
if (SZ(S[x]) < SZ(S[y])) swap(x, y);
p[y] = x;
for (auto it: S[y]) {
auto suf = S[x].lower_bound(it);
if (suf != S[x].end()) update(it, *suf);
if (suf != S[x].begin()) update(*prev(suf), it);
S[x].insert(it);
}
S[y].clear();
}
int main() {
re(n), re(q);
scanf("%s", s + 1);
sa.get_sa(s, n);
sa.get_height(s);
for (int i = 1; i <= n; i++) p[i] = i, S[i].insert(i);
for (int i = 2; i <= n; i++) H[i - 1] = {sa.height[i], i};
sort(H + 1, H + n);
ctr.build(ctr.root[n], 1, n);
for (int i = n - 1, j = n - 1; i >= 1; i--) {
cnt = 0, tmp.clear();
while (j && H[j].first == i) {
int idx = H[j--].second;
Union(sa.sa[idx], sa.sa[idx - 1]);
}
sort(id, id + cnt);
for (int i = cnt - 1; i >= 0; i--) {
tmp.pb({id[i], updated[id[i]]}), updated[id[i]] = 0;
}
if (tmp.empty())
ctr.root[i] = ctr.root[i + 1];
else
ctr.modify(ctr.root[i + 1], ctr.root[i], 1, n);
#ifdef ROSHIN
printf("L=%d\n",i);
for (auto t: tmp) {
cout << t.first << " " << t.se;
}
cout << endl;
#endif
}
while (q--) {
int L, R;
re(L), re(R);
int l = 0, r = R - L;
while (l < r) {
int mid = (l + r + 1) >> 1;
if (ctr.query(ctr.root[mid], 1, n, L, R - mid) <= R - mid + 1) l = mid;
else r = mid - 1;
}
printf("%d\n", l);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】