Finally finished Jiayuan sister series
Suffix array + RMQ + chairman tree
This problem is to find the LCS in two segment substrings
Of course, LCS can be calculated by LCP
Set up SA first
Get a,b,c,d and get rk-c
Binary LCS set query mid
Because the LCP of two strings is min of rk1-rk2
Building ST tables
Using RMQ to find out the interval L,R that rkc can cover
It's obvious at this timeIt's legal to appear in L-R
So easy to get interval version query
Just set up the tree query node
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const int N=1e6+1000; char S[N]; int x[N]; int y[N]; int c[N]; int SA[N]; int n,m; void Get_SA(){ for(int i=1;i<=n;++i)x[i]=S[i]; for(int i=1;i<=n;++i)++c[x[i]]; for(int i=1;i<=m;++i)c[i]+=c[i-1]; for(int i=n;i>=1;i--)SA[c[x[i]]--]=i; for(int k=1;k<=n;k=k<<1){ int num=0; for(int i=n-k+1;i<=n;++i)y[++num]=i; for(int i=1;i<=n;++i)if(SA[i]>k)y[++num]=SA[i]-k; for(int i=1;i<=m;++i)c[i]=0; for(int i=1;i<=n;++i)++c[x[i]]; for(int i=1;i<=m;++i)c[i]+=c[i-1]; for(int i=n;i>=1;--i)SA[c[x[y[i]]]--]=y[i],y[i]=0; swap(x,y); num=1; x[SA[1]]=1; for(int i=2;i<=n;++i)x[SA[i]]=(y[SA[i]]==y[SA[i-1]]&&y[SA[i]+k]==y[SA[i-1]+k])?num:++num; if(n==num)break; m=num; } } int rk[N]={}; int height[N]={}; void Get_Height(){ for(int i=1;i<=n;++i)rk[SA[i]]=i; int k=0; for(int i=1;i<=n;++i){ if(rk[i]==1)continue; if(k)k--; int Id=SA[rk[i]-1]; while(Id+k<=n&&i+k<=n&&S[Id+k]==S[i+k])++k; height[rk[i]]=k; } } int st[N][20]={}; void Get_RMQ(){ memset(st,0x3f,sizeof(st)); for(int i=1;i<=n;++i){ st[i][0]=height[i]; } for(int j=1;j<=20;++j) for(int i=1;i<=n;++i){ if(i+(1<<(j-1))>n)break; st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]); } } int lson[N*10]={}; int rson[N*10]={}; int root[N]={}; int sum[N*10]={}; int cnt=0; void Update(int x,int &y,int l,int r,int pos){ y=++cnt; lson[y]=lson[x]; rson[y]=rson[x]; sum[y]=sum[x]+1; if(l==r)return; int mid=(l+r)/2; if(pos<=mid) Update(lson[x],lson[y],l,mid,pos); else Update(rson[x],rson[y],mid+1,r,pos); } int Query(int x,int y,int l,int r,int dl,int dr){ if(dl<=l&&r<=dr){ return sum[y]-sum[x]; } int mid=(l+r)/2; int ret=0; if(dl<=mid)ret+=Query(lson[x],lson[y],l,mid,dl,dr); if(mid< dr)ret+=Query(rson[x],rson[y],mid+1,r,dl,dr); return ret; } int main(){ int Q; // freopen("test.in","r",stdin); // freopen("test.out","w",stdout); scanf("%d%d",&n,&Q); scanf("%s",S+1); m=200; Get_SA(); Get_Height(); Get_RMQ(); for(int i=1;i<=n;++i)Update(root[i-1],root[i],1,n,rk[i]); while(Q--){ int a,b,c,d; scanf("%d%d%d%d",&a,&b,&c,&d); int l=1; int r=min((b-a+1),(d-c+1)); int ans=0; while(l<=r){ int L,R; L=R=rk[c]; int mid=(l+r)/2; for(int i=20;i>=0;i--)if(L-(1<<i)>=0&&st[L-(1<<i)+1][i]>=mid)L=L-(1<<i); for(int i=20;i>=0;i--)if(R+(1<<i)<=n&&st[R+1][i]>=mid)R=R+(1<<i); if(Query(root[a-1],root[b-mid+1],1,n,L,R)>0)ans=mid,l=mid+1; else r=mid-1; } cout<<ans<<'\n'; } }