记录编号 |
266885 |
评测结果 |
EEEEEEEEEEE |
题目名称 |
[HEOI 2016] 字符串 |
最终得分 |
0 |
用户昵称 |
Aglove |
是否通过 |
未通过 |
代码语言 |
C++ |
运行时间 |
0.814 s |
提交时间 |
2016-06-10 06:38:40 |
内存使用 |
101.98 MiB |
显示代码纯文本
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdlib>
using namespace std;
const int maxn=200010;
int n,m,tot,la;
int a,b,c,d;
char s[maxn];
int p[maxn];
struct Node{
int next[26];
int len,link;
}st[maxn];
int h[maxn],cnt=0;
struct edge{
int to,next;
}G[maxn<<1];
int anc[maxn][20],dep[maxn];
int pos[maxn],end[maxn],sum=0;
int rt[maxn];
struct Seg_Tree{
int L,R,v;
}t[5000010];
void add(int x,int y){
++cnt;G[cnt].to=y;G[cnt].next=h[x];h[x]=cnt;
}
void read(int &num){
num=0;char ch=getchar();
while(ch<'!')ch=getchar();
while(ch>='0'&&ch<='9')num=num*10+ch-'0',ch=getchar();
}
void init(){
tot=la=0;
st[0].link=-1;
}
int insert(int c){
int cur=++tot;
st[cur].len=st[la].len+1;
int p;
for(p=la;p!=-1&&st[p].next[c]==0;p=st[p].link)st[p].next[c]=cur;
if(p==-1)st[cur].link=0;
else{
int q=st[p].next[c];
if(st[q].len==st[p].len+1)st[cur].link=q;
else{
int clone=++tot;
st[clone]=st[q];
st[clone].len=st[p].len+1;
for(;p!=-1&&st[p].next[c]==q;p=st[p].link)st[p].next[c]=clone;
st[q].link=st[cur].link=clone;
}
}la=cur;return la;
}
void DFS(int u,int f){
anc[u][0]=f;pos[u]=++sum;
for(int i=h[u];i;i=G[i].next){
int v=G[i].to;
if(v==f)continue;
dep[v]=dep[u]+1;
//printf("%d %d\n",u,v);
DFS(v,u);
}end[u]=sum;
}
void pre_LCA(){
for(int i=0;i<=tot;++i){
for(int j=1;(1<<j)<=tot;++j)anc[i][j]=-1;
}
for(int j=1;(1<<j)<=tot;++j){
for(int i=1;i<=tot;++i){
if(anc[i][j-1]!=-1){
int a=anc[i][j-1];
anc[i][j]=anc[a][j-1];
}
}
}return;
}
void build(int &o,int L,int R){
o=++cnt;
if(L==R)return;
int mid=(L+R)>>1;
build(t[o].L,L,mid);
build(t[o].R,mid+1,R);
}
void UPD(int &o,int L,int R,int p){
t[++cnt]=t[o];o=cnt;
if(L==R){t[o].v++;return;}
int mid=(L+R)>>1;
if(p<=mid)UPD(t[o].L,L,mid,p);
else UPD(t[o].R,mid+1,R,p);
t[o].v=t[t[o].L].v+t[t[o].R].v;
}
int ask(int o,int L,int R,int x,int y){
if(L>=x&&R<=y)return t[o].v;
int mid=(L+R)>>1;
if(y<=mid)return ask(t[o].L,L,mid,x,y);
else if(x>mid)return ask(t[o].R,mid+1,R,x,y);
else return ask(t[o].L,L,mid,x,y)+ask(t[o].R,mid+1,R,x,y);
}
int find(int p){
int log;
for(log=0;(1<<log)<=dep[p];++log);--log;
for(int i=log;i>=0;--i){
if(anc[p][i]!=-1&&st[anc[p][i]].len>=d-c+1){
p=anc[p][i];
}
}return p;
}
int Get_pos(int p,int k){
int log;
for(log=0;(1<<log)<=dep[p];++log);--log;
for(int i=log;i>=0;--i){
if(anc[p][i]!=-1&&dep[anc[p][i]]>=k)p=anc[p][i];
}return p;
}
bool check(int u){
int L,B,A;
if(st[u].link==-1)L=0;
else L=st[st[u].link].len+1;
if(b-a+1<L)return false;
B=ask(rt[b-L+1],1,sum,pos[u],end[u]);
A=ask(rt[a-1],1,sum,pos[u],end[u]);
if(B-A>0)return true;
else return false;
}
bool judge(int u,int L){
int A,B;
if(b-a+1<L)return false;
B=ask(rt[b-L+1],1,sum,pos[u],end[u]);
A=ask(rt[a-1],1,sum,pos[u],end[u]);
if(B-A>0)return true;
else return false;
}
void debug(){
for(int i=0;i<=tot;++i){
for(int j=0;j<26;++j){
if(st[i].next[j]){
printf("%d -> %d %c\n",i,st[i].next[j],j+'a');
}
}
}printf("\n");
}
void Get_s(){
int len=0;
char ch=getchar();
while(ch<'!')ch=getchar();
while(ch>='a'&&ch<='z')s[++len]=ch,ch=getchar();
}
int main(){
freopen("heoi2016_str.in","r",stdin);
freopen("heoi2016_str.out","w",stdout);
int __size__=32<<20;
char *__p__=(char*)malloc(__size__)+__size__;
__asm__("movl %0, %%esp\n"::"r"(__p__));
read(n);read(m);init();
Get_s();
for(int i=n;i>=1;--i)p[i]=insert(s[i]-'a');
for(int i=1;i<=tot;++i)add(st[i].link,i);
DFS(0,-1);cnt=0;build(rt[0],1,sum);
for(int i=1;i<=n;++i){
rt[i]=rt[i-1];
UPD(rt[i],1,sum,pos[p[i]]);
}pre_LCA();
while(m--){
read(a);read(b);read(c);read(d);
int u=find(p[c]);
int L=0,R=dep[u];
while(L<R){
int mid=L+((R-L+1)>>1);
int v=Get_pos(u,mid);
if(check(v))L=mid;
else R=mid-1;
}
u=Get_pos(u,L);
int A,B;
if(st[u].link==-1)A=0;
else A=st[st[u].link].len+1;
B=st[u].len;
while(A<B){
int mid=A+((B-A+1)>>1);
if(judge(u,mid))A=mid;
else B=mid-1;
}A=min(A,d-c+1);
printf("%d\n",A);
}return 0;
}