或者哪位一样的提供建议吧qwq
#include<iostream>
#include<cstring>
using namespace std;
const int N=2e5+10;
struct smt_node{
int ls,rs;
int val;
};
smt_node smt[80*N];
int cnt;
inline int smt_copynode(int now){
return smt[++cnt]=smt[now],cnt;
}
void smt_ins(int &now,int l,int r,int pos){
if(!now) now=++cnt;
smt[now].val|=1;
if(l==r) return ;
int mid=l+r>>1;
if(pos<=mid) smt_ins(smt[now].ls,l,mid,pos);
else smt_ins(smt[now].rs,mid+1,r,pos);
}
bool smt_query(int now,int l,int r,int ql,int qr){
if(!now) return false;
if(l>=ql&&r<=qr) return smt[now].val;
int mid=l+r>>1,ans=false;
if(ql<=mid) ans|=smt_query(smt[now].ls,l,mid,ql,qr);
else ans|=smt_query(smt[now].rs,mid+1,r,ql,qr);
return ans;
}
int smt_merge(int x,int y,int l,int r){
if(!x||!y) return smt_copynode(x|y);
x=smt_copynode(x),smt[x].val|=smt[y].val;
int mid=l+r>>1;
smt[x].ls=smt_merge(smt[x].ls,smt[y].ls,l,mid);
smt[x].rs=smt_merge(smt[x].rs,smt[y].rs,mid+1,r);
return x;
}
int posit[N];
struct prt_node{
int fa,len;
int rt;
};
struct suffix_automaton{
prt_node prt[2*N];
int ch[2*N][26];
int last,tot;
suffix_automaton(){
last=tot=1;
}
void add(int c,int pos,int n){
int p=last,np=last=++tot;
prt[np].len=prt[p].len+1;
smt_ins(prt[np].rt,1,n,pos);
posit[pos]=np;
while(p&&!ch[p][c]){
ch[p][c]=np;
p=prt[p].fa;
}
if(!p) return void(prt[np].fa=1);
int q=ch[p][c];
if(prt[q].len==prt[p].len+1)
return void(prt[np].fa=q);
int nq=++tot;
prt[nq].len=prt[p].len+1;
prt[nq].fa=prt[q].fa;
prt[q].fa=prt[np].fa=nq;
for(int i=0;i<26;i++)
ch[nq][c]=ch[q][c];
while(p&&ch[p][c]==q){
ch[p][c]=nq;
p=prt[p].fa;
}
}
};
suffix_automaton sam;
struct edge_node{
int from,to;
int nxt;
};
struct edge{
edge_node e[2*N];
int head[2*N],tot;
edge(){
memset(head,-1,sizeof head);
tot=0;
}
inline void add(int from,int to){
e[tot].from=from;
e[tot].to=to;
e[tot].nxt=head[from];
head[from]=tot++;
}
};
edge e;
int n,m;
int f[2*N][30],dep[2*N];
void dfs(int u,int fa){
f[u][0]=fa,dep[u]=dep[fa]+1;
for(int i=1;i<=20;i++) f[u][i]=f[f[u][i-1]][i-1];
for(int i=e.head[u];~i;i=e.e[i].nxt){
int v=e.e[i].to;dfs(v,u);
sam.prt[u].rt=smt_merge(sam.prt[u].rt,sam.prt[v].rt,1,n);
}
}
int get_pos(int x,int len){
for(int i=20;i>=0;i--)
if(sam.prt[f[x][i]].len>=len)
x=f[x][i];
return x;
}
bool check(int l1,int r1,int l2,int r2){
int len=r1-l1+1,p=get_pos(posit[r1],len);
return smt_query(sam.prt[p].rt,1,n,l2+len-1,r2);
}
int binary_search(int l1,int r1,int l2,int r2){
int l=l1,r=r1,ans;
while(l<=r){
int mid=l+r>>1;
if(check(l1,mid,l2,r2)) ans=mid,l=mid+1;
else r=mid-1;
}
return ans-l1+1;
}
string s;
int main(){
cin>>n>>m;
cin>>s;
for(int i=0;i<=n-1;i++)
sam.add(s[i]-'a',i+1,n);
for(int i=2;i<=sam.tot;i++)
e.add(sam.prt[i].fa,i);
dfs(1,0);
for(int i=1;i<=m;i++){
int l1,r1,l2,r2;
cin>>l1>>r1>>l2>>r2;
cout<<binary_search(l2,r2,l1,r1)<<'\n';
}
}