记录编号 254368 评测结果 AAAAAAAAAAA
题目名称 [HEOI 2016] 字符串 最终得分 100
用户昵称 Gravatarstdafx.h 是否通过 通过
代码语言 C++ 运行时间 11.844 s
提交时间 2016-04-25 09:48:07 内存使用 54.55 MiB
显示代码纯文本
#define maxn 100010ul
#define maxt 4000010ul

#include <math.h>
#include <stdio.h>
#include <algorithm>

typedef unsigned int uint;

const int inf=0x3fffffff;
const uint base=131;

uint mp[maxn],pw[maxn];
int n,q,tot,st[17][maxn],rank[maxn],sa[maxn],L[maxt],R[maxt],tree[maxt],root[maxn];
char str[maxn];

void read(int &x){
	x=0;int c=getchar();
	while(c<'0'||c>'9') c=getchar();
	for(;c>='0'&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
	return;
}

uint hsp(int l,int r){
	return mp[r]-mp[l-1]*pw[r-l+1];
}

int lcp(int a,int b,int c,int d){
	if(!a) return 0;
	int ret=0,mid,l=1,r=std::min(d-c+1,b-a+1);
	while(l<=r){
		mid=(l+r)>>1;
		if(hsp(a,a+mid-1)==hsp(c,c+mid-1)) l=mid+1,ret=mid;
		else r=mid-1;
	}
	return ret;
}

bool cmp(int a,int b){
	int ret=lcp(a,n,b,n),len=std::min(n-a+1,n-b+1);
	return ret==len?n-a<n-b:str[a+ret]<str[b+ret];
}

void build(int ls,int &rt,int l,int r,int pos){
	rt=++tot,L[rt]=L[ls],R[rt]=R[ls];
	tree[rt]=tree[ls]+1;
	if(l==r) return;
	int mid=(l+r)>>1;
	if(pos<=mid) build(L[ls],L[rt],l,mid,pos);
	else build(R[ls],R[rt],mid+1,r,pos);
	return;
}

void prepare(){
	pw[0]=1;for(int i=1;i<=n;i++) pw[i]=pw[i-1]*base;
	for(int i=1;i<=n;i++) mp[i]=mp[i-1]*base+str[i];
	for(int i=1;i<=n;i++) sa[i]=i;
	std::sort(sa+1,sa+n+1,cmp);
	for(int i=1;i<=n;i++) rank[sa[i]]=i;
	for(int i=1;i<=n;i++) build(root[i-1],root[i],1,n,rank[i]);
	for(int i=1;i<=n;i++) st[0][i]=lcp(sa[i-1],n,sa[i],n);
	for(int i=1;i<17;i++) for(int j=1<<i;j<=n;j++)
	    st[i][j]=std::min(st[i-1][j],st[i-1][j-(1<<(i-1))]);
	return;
}

int query(int ls,int rt,int l,int r,int posl,int posr){
	if(posl<=l&&posr>=r) return tree[rt]-tree[ls];
	int ret=0,mid=(l+r)>>1;
	if(posl<=mid) ret+=query(L[ls],L[rt],l,mid,posl,posr);
	if(posr>mid) ret+=query(R[ls],R[rt],mid+1,r,posl,posr);
	return ret;
}

bool check(int len,int a,int b,int c,int d){
	int s=rank[c],e=rank[c];
	for(int i=16;i>=0;i--) if(s>(1<<i)&&st[i][s]>=len) s-=1<<i;
	for(int i=16;i>=0;i--) if(e+(1<<i)<=n&&st[i][e+(1<<i)]>=len) e+=1<<i;
	return query(root[a-1],root[b-len+1],1,n,s,e)>0;
}

int main(){
	freopen("heoi2016_str.in","r",stdin);
	freopen("heoi2016_str.out","w",stdout);
	read(n),read(q);
	scanf("%s",str+1);
	prepare();
	for(int i=1,a,b,c,d,l,r,mid,ret;i<=q;i++){
		read(a),read(b),read(c),read(d);
		l=1,r=std::min(b-a+1,d-c+1),ret=0;
		while(l<=r){
			mid=(l+r)>>1;
			if(check(mid,a,b,c,d)) l=mid+1,ret=mid;
			else r=mid-1;
		}
		printf("%d\n",ret);
	}
	return 0;
}