给出只包含小写拉丁字母的字符串 S ,有 m 个询问,给出 (a,b,c,d) ,求属于区间 [a,b] 的所有子串与 S[c..d] 的 LCP 长度最大值。
1≤|S|,m≤105
显然可以使用后缀数组,我们要求的是
#include
#include
#include
#include
using namespace std;
int read()
{
int x=0,f=1;
char ch=getchar();
while (!isdigit(ch)) f=ch=='-'?-1:f,ch=getchar();
while (isdigit(ch)) x=x*10+ch-'0',ch=getchar();
return x*f;
}
const int N=105000;
const int LGN=17;
const int S=N*LGN;
struct chairman_tree
{
int son[S][2],size[S];
int tot;
int newnode(int cp)
{
size[++tot]=size[cp],son[tot][0]=son[cp][0],son[tot][1]=son[cp][1];
return tot;
}
void add(int &rt,int rt0,int x,int l,int r)
{
rt=newnode(rt0);
size[rt]++;
if (l==r) return;
int mid=l+r>>1;
if (x<=mid) add(son[rt][0],son[rt0][0],x,l,mid);
else add(son[rt][1],son[rt0][1],x,mid+1,r);
}
int gol(int rt,int rt0,int l,int r)
{
if (!(size[rt]-size[rt0])) return -1;
if (l==r) return l;
int mid=l+r>>1,ret;
ret=gol(son[rt][0],son[rt0][0],l,mid);
if (ret!=-1) return ret;
return gol(son[rt][1],son[rt0][1],mid+1,r);
}
int searchl(int rt,int rt0,int st,int en,int l,int r)
{
if (st>en) return -1;
if (!(size[rt]-size[rt0])) return -1;
if (st==l&&en==r) return gol(rt,rt0,l,r);
int mid=l+r>>1,ret;
if (en<=mid) return searchl(son[rt][0],son[rt0][0],st,en,l,mid);
else if (mid+1<=st) return searchl(son[rt][1],son[rt0][1],st,en,mid+1,r);
else
{
ret=searchl(son[rt][0],son[rt0][0],st,mid,l,mid);
if (ret!=-1) return ret;
return searchl(son[rt][1],son[rt0][1],mid+1,en,mid+1,r);
}
}
int gor(int rt,int rt0,int l,int r)
{
if (!(size[rt]-size[rt0])) return -1;
if (l==r) return l;
int mid=l+r>>1,ret;
ret=gor(son[rt][1],son[rt0][1],mid+1,r);
if (ret!=-1) return ret;
return gor(son[rt][0],son[rt0][0],l,mid);
}
int searchr(int rt,int rt0,int st,int en,int l,int r)
{
if (st>en) return -1;
if (!(size[rt]-size[rt0])) return -1;
if (st==l&&en==r) return gor(rt,rt0,l,r);
int mid=l+r>>1,ret;
if (en<=mid) return searchr(son[rt][0],son[rt0][0],st,en,l,mid);
else if (mid+1<=st) return searchr(son[rt][1],son[rt0][1],st,en,mid+1,r);
else
{
ret=searchr(son[rt][1],son[rt0][1],mid+1,en,mid+1,r);
if (ret!=-1) return ret;
return searchr(son[rt][0],son[rt0][0],st,mid,l,mid);
}
}
}t;
int Ws[N],Wv[N],x[N],y[N],rank[N],SA[N],height[N],root[N];
int rmq[N][LGN];
int n,m,lgn,ans;
char s[N];
bool cmp(int *r,int st1,int st2,int l){return st1+lint i,l=1,p,mx;
for (mx=0,i=0;ix[i]=s[i]-'a');
for (i=0;i<=mx;i++) Ws[i]=0;
for (i=0;ifor (i=1;i<=mx;i++) Ws[i]+=Ws[i-1];
for (i=n-1;i>=0;i--) SA[--Ws[Wv[i]]]=i;
for (x[SA[0]]=p=0,i=1;ix[SA[i]]=(p+=s[SA[i]]!=s[SA[i-1]]);
for (;l<=n&&p!=n-1;l<<=1)
{
for (p=0,i=n-l;iy[p++]=i;
for (i=0;iif (SA[i]>=l) y[p++]=SA[i]-l;
for (mx=0,i=0;ix[y[i]]);
for (i=0;i<=mx;i++) Ws[i]=0;
for (i=0;ifor (i=1;i<=mx;i++) Ws[i]+=Ws[i-1];
for (i=n-1;i>=0;i--) SA[--Ws[Wv[i]]]=y[i];
for (i=0;iy[i]=x[i],x[i]=0;
for (x[SA[0]]=p=0,i=1;ix[SA[i]]=(p+=!cmp(y,SA[i-1],SA[i],l));
}
for (i=0;ifor (int i=0,j,k=0;iif (!rank[i]) continue;
j=SA[rank[i]-1];
for (;i+ks[i+k]==s[j+k];) k++;
height[rank[i]]=k;
}
}
void pre()
{
lgn=trunc(log(n)/log(2));
for (int i=0;iq[i][0]=height[i];
for (int j=1;j<=lgn;j++)
for (int i=0;i+(1<1if (rmq[i][j-1]q[i+(1<[j-1]) rmq[i][j]=rmq[i][j-1];
else rmq[i][j]=rmq[i+(1<[j-1];
for (int i=0;i1 ]:0,rank[i],0,n-1);
}
int getrmq(int l,int r)
{
int lgr=trunc(log(r-l+1)/log(2));
return rmq[l][lgr]q[r-(1<[lgr]?rmq[l][lgr]:rmq[r-(1<[lgr];
}
int get(int st,int en,int x)
{
int y=t.searchr(root[en],st?root[st-1]:0,0,rank[x],0,n-1),ret=0;
if (y!=-1) ret=y!=rank[x]?getrmq(y+1,rank[x]):n-SA[y];
y=t.searchl(root[en],st?root[st-1]:0,rank[x],n-1,0,n-1);
if (y!=-1) ret=max(ret,y!=rank[x]?getrmq(rank[x]+1,y):n-SA[y]);
return ret;
}
int LCP(int st,int en,int x)
{
int l=st,r=en,mid,tmp,ret=0;
while (l<=r)
{
mid=l+r>>1;
tmp=get(st,mid,x);
if (tmp>=en-mid+1) ret=en-mid+1,r=mid-1;
else l=mid+1;
}
return ret;
}
void solve()
{
for (int i=1,a,b,c,d;i<=m;i++)
{
a=read()-1,b=read()-1,c=read()-1,d=read()-1;
ans=LCP(a,b,c);
ans=min(ans,d-c+1);
printf("%d\n",ans);
}
}
int main()
{
freopen("string.in","r",stdin),freopen("string.out","w",stdout);
n=read(),m=read();
scanf("%s",s);
DA(),getheight(),pre();
solve();
fclose(stdin),fclose(stdout);
return 0;
}