the
Give a 01 string of length n, each time ask for an interval [l,r], ask all the end position in [l,r] prefix, 22 LCS maximum value.
n,m≤105 N, m≤10 5 n,m\le10^5 Analysis
Obviously a prefix to (x,y) can contribute to all satisfying l≤x,y≤r l≤x, y≤r l\le x,y\le R's Inquiries [L,r] [L, R] [L,r].
The two-prefix LCS is equivalent to the MX of LCA on Sam's parents tree. So we can build the SAM first, use set to maintain the right set of the current point, and then heuristic merge from bottom to top.
Each time a two set is merged, all newly added neighboring points are removed, and the weights are the MX of the current point, so only O (NLOGN) o (n l o g N) O (NLOGN) point pairs can contribute.
The rest is a two-dimensional point problem, with the scan line + tree array to do it. Code
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <
algorithm> #include <set> const int n=100005;
int n,m,sz,ls,b[n*2],c[n*2],t[n],ch[n*2][2],mx[n*2],tot,fa[n*2],ans[n];
Char Str[n]; struct Data{int x,y,id;}
A[n*30],q[n];
Std::set<int> Se[n*2];
Std::set<int>::iterator it,it1;
void extend (int x) {int p,q,np,nq;
p=ls;ls=np=++sz;mx[np]=mx[p]+1;
For (;p &&!ch[p][x];p =fa[p]) CH[P][X]=NP;
if (!p) fa[np]=1;
else {q=ch[p][x];
if (mx[q]==mx[p]+1) fa[np]=q;
else {nq=++sz;mx[nq]=mx[p]+1;
memcpy (ch[nq],ch[q],sizeof (ch[q));
FA[NQ]=FA[Q];FA[Q]=FA[NP]=NQ;
for (; ch[p][x]==q;p=fa[p]) ch[p][x]=nq;
} void Pre () {for (int i=1;i<=sz;i++) b[mx[i]]++;
for (int i=1;i<=sz;i++) b[i]+=b[i-1];
for (int i=sz;i>=1;i--) c[b[mx[i]]--]=i; for (int i=sz;i>=2;i--) {int x=c[I],y=fa[x];
if (Se[x].size () >se[y].size ()) Std::swap (Se[x],se[y]);
For (It=se[x].begin (); It!=se[x].end (); it++) {int w=*it;
It1=se[y].lower_bound (w);
if (It1!=se[y].end ()) a[++tot]= (data) {W,*it1,mx[y]};
if (It1!=se[y].begin ()) it1--, a[++tot]= (data) {*it1,w,mx[y]};
For (It=se[x].begin (); It!=se[x].end (); it++) Se[y].insert (*it);
} BOOL CMP (data A,data b) {return a.x>b.x;}
void ins (int x,int y) {while (x<=n) T[x]=std::max (t[x],y),x+=x& (-X);}
int query (int x) {int ans=0;
while (x) Ans=std::max (ans,t[x]),x-=x& (-X);
return ans;
int main () {scanf ("%d%d", &n,&m);
scanf ("%s", str+1);
Ls=sz=1;
for (int i=1;i<=n;i++) extend (str[i]-' 0 '), Se[ls].insert (i);
Pre ();
Std::sort (A+1,A+TOT+1,CMP);
for (int i=1;i<=m;i++) scanf ("%d%d", &q[i].x,&q[i].y), q[i].id=i;
Std::sort (Q+1,Q+M+1,CMP);
int p=1; for (int i=1;i<=m;i++) {while (p<=tot&&a[p].x>=q[i].x) ins (a[p].y,a[p].id), p++;
Ans[q[i].id]=query (Q[I].Y);
for (int i=1;i<=m;i++) printf ("%d\n", Ans[i]);
return 0; }