码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ4556 HEOI2016字符串

时间:2018-03-11 22:29:30      阅读:205      评论:0      收藏:0      [点我收藏+]

标签:eve   printf   turn   自动机   clu   work   ever   div   else   

没错,又是这题,使用后缀自动机,反向建树,主席树维护right集合。

By:大奕哥

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int N=2e5+10;
  4 int rt[N],num,n,q,aa,bb,cc,dd,cnt,head[N],fa[N][19];
  5 char s[N];
  6 struct tree{
  7     int l,r;
  8 }t[N*50];
  9 void change(int &x,int l,int r,int p)
 10 {
 11     if(!x)x=++num;
 12     if(l==r)return;
 13     int mid=l+r>>1;
 14     if(p>mid)change(t[x].r,mid+1,r,p);
 15     else change(t[x].l,l,mid,p);
 16 }
 17 void merge(int &x,int y)
 18 {
 19     if(!x||!y){x=x+y;return;}
 20     ++num;t[num]=t[x];x=num;
 21     merge(t[x].l,t[y].l);
 22     merge(t[x].r,t[y].r);
 23 }
 24 bool query(int x,int l,int r,int L,int R)
 25 {
 26     if(!x)return 0;
 27     if(l==L&&r==R)return 1;
 28     int mid=l+r>>1;
 29     if(mid<L)return query(t[x].r,mid+1,r,L,R);
 30     else if(mid>R)return query(t[x].l,l,mid,L,R);
 31     else return query(t[x].l,l,mid,L,mid)|query(t[x].r,mid+1,r,mid+1,R); 
 32 }
 33 struct edge{
 34     int to,nex;
 35 }e[N];
 36 void addedge(int x,int y)
 37 {
 38     e[++cnt].to=y;e[cnt].nex=head[x];head[x]=cnt;
 39 }
 40 void dfs(int x)
 41 {
 42     for(int i=1;i<=18;++i)fa[x][i]=fa[fa[x][i-1]][i-1];
 43     for(int i=head[x];i;i=e[i].nex)
 44     {
 45         int y=e[i].to;
 46         fa[y][0]=x;dfs(y);
 47     }
 48 }
 49 struct SAM
 50 {
 51     int cnt,root,last,c[N][26],f[N],dp[N],tt[N],pos[N],p[N],r[N],id[N],l[N];
 52     SAM(){cnt=0;last=root=++cnt;}
 53     void add(int x,int dd)
 54     {
 55         int now=last,a=++cnt;last=a;id[a]=dd;
 56         l[a]=l[now]+1;p[dd]=a;
 57         for(;now&&!c[now][x];now=f[now])c[now][x]=a;
 58         if(!now)f[a]=root;
 59         else{
 60             int q=c[now][x];
 61             if(l[q]==l[now]+1)f[a]=q;
 62             else{
 63                 int b=++cnt;id[b]=dd;
 64                 l[b]=l[now]+1;
 65                 f[b]=f[q];
 66                 f[a]=f[q]=b;
 67                 memcpy(c[b],c[q],sizeof(c[q]));
 68                 for(;now&&c[now][x]==q;now=f[now])c[now][x]=b;
 69             }
 70         }
 71         return;
 72     }
 73     void sort(){
 74         for(int i=1;i<=cnt;++i)tt[l[i]]++;
 75         for(int i=1;i<=n;++i)tt[i]+=tt[i-1];
 76         for(int i=1;i<=cnt;++i)r[tt[l[i]]--]=i;
 77         return;
 78     }
 79     bool judge(int x,int ll)
 80     {
 81         for(int i=18;i>=0;--i)
 82         if(l[fa[x][i]]>=ll)x=fa[x][i];
 83         return query(rt[x],1,n,aa+ll-1,bb);
 84     }
 85     void work()
 86     {
 87         for(int i=cnt;i>=2;--i)
 88         {
 89             int x=r[i];
 90             change(rt[x],1,n,id[x]);
 91             merge(rt[f[x]],rt[x]);
 92             addedge(f[x],x);
 93         }dfs(1);int ans=0;
 94         for(int i=1;i<=q;++i)
 95         {
 96             
 97             scanf("%d%d%d%d",&aa,&bb,&cc,&dd);
 98             int ll=1,rr=min(bb-aa+1,dd-cc+1);ans=0;
 99             aa=n-aa+1;bb=n-bb+1;cc=n-cc+1;dd=n-dd+1;
100             swap(aa,bb);swap(cc,dd);int x=p[dd];
101             while(ll<=rr)
102             {
103                 int mid=ll+rr>>1;
104                 if(judge(x,mid))ll=mid+1,ans=mid;
105                 else rr=mid-1;
106             }
107             printf("%d\n",ans);
108         }
109         return;
110     }
111 }A;
112 int main()
113 {
114     scanf("%d%d",&n,&q);
115     scanf("%s",s+1);
116     reverse(s+1,s+1+n);
117     for(int i=1;i<=n;++i)A.add(s[i]-a,i);
118     A.sort();A.work();
119     return 0;
120 }

 

BZOJ4556 HEOI2016字符串

标签:eve   printf   turn   自动机   clu   work   ever   div   else   

原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8546225.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!