bzoj 4556 字符串

来源:互联网 发布:电脑桌面 知乎 编辑:程序博客网 时间:2024/05/24 07:07

后缀数组,暴力硬跑
贼快

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cmath>#define MAXN 100005using namespace std;int buc[MAXN],wa[MAXN],wb[MAXN];int r[MAXN],sa[MAXN],rank[MAXN],height[MAXN];void getheight(int n){    int i,j,k=0;    for(i=0;i<n;i++)rank[sa[i]]=i;    for(i=0;i<n;height[rank[i++]]=k)        for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);    return ;}bool cmp(int *c,int a,int b,int d)    {return c[a]==c[b]&&c[a+d]==c[b+d];}void da(int n,int m=130){    int i,j,p,*x=wa,*y=wb,*t;    for(i=0;i<m;i++)buc[i]=0;    for(i=0;i<n;i++)buc[x[i]=r[i]]++;    for(i=1;i<m;i++)buc[i]+=buc[i-1];    for(i=n-1;~i;i--)sa[--buc[x[i]]]=i;    for(j=1,p=1;p<n;j*=2,m=p){        for(i=n-j,p=0;i<n;i++)y[p++]=i;        for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;        for(i=0;i<m;i++)buc[i]=0;        for(i=0;i<n;i++)buc[x[y[i]]]++;        for(i=1;i<m;i++)buc[i]+=buc[i-1];        for(i=n-1;~i;i--)sa[--buc[x[y[i]]]]=y[i];        for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)            x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;    }    getheight(n);    return ;}int n,q;char s[MAXN];int main(){    scanf("%d%d",&n,&q);    scanf("%s",s);    for(int i=0;i<n;i++)r[i]=s[i];    da(n+1);    int ans,minn,pos,now,a,b,c,d;    while(q--){        scanf("%d%d%d%d",&a,&b,&c,&d);        a--;b--;c--;d--;        ans=0; minn=min(d-c+1,b-a+1);         pos=rank[c];         if(sa[pos]>=a&&sa[pos]<=b)ans=max(ans,min(minn,min(b-sa[pos]+1,d-c+1)));        minn=min(minn,height[pos]);        for(int i=pos-1;i>=0;i--){            if(minn<=ans)break;            now=sa[i];            if(now>=a&&now<=b)ans=max(ans,min(minn,min(b-sa[i]+1,d-c+1)));            minn=min(minn,height[i]);        }        minn=min(d-c+1,b-a+1);        for(int i=pos+1;i<=n;i++){            minn=min(minn,height[i]);            if(minn<=ans)break;            now=sa[i];            if(now>=a&&now<=b){ans=max(ans,min(minn,min(b-sa[i]+1,d-c+1)));}        }        printf("%d\n",ans);    }    return 0;}
原创粉丝点击