codeforces 700E 后缀数组
来源:互联网 发布:床品品牌知乎 编辑:程序博客网 时间:2024/06/11 04:31
题意:定义a串比b串优当且仅当a串中至少包含两个b串(可以重叠),给出一个串w,求一个最长的由w的子串构成的序列,满足第i个串比第i-1个串优。
题解后缀自动机没看懂,看了评论中的一个后缀数组做法。
定义一个串是好串当该串长度为1或该串的前缀和后缀都有同一个好串且该好串不出现在该串中间。
那么对于每一个后缀取一个最长的是后缀前缀的好串,最终答案一定由这些好串组成。
从n到1枚举求是当前串前缀的最长好串,在线段树上查询当前好串的前缀好串,用线段树维护已插入的编号最小值,查询前缀为前缀好串的最小编号。计算出当前好串的长度。在第一棵线段树上区间修改,第二棵线段树上单点修改。
说的不是很明白,看代码吧。。。
#include <bits/stdc++.h>using namespace std;#define N 210000#define ls l,mid,now<<1#define rs mid+1,r,now<<1|1int n,ans;char s[N];int tr[N],ran[N],sa[N],h[N][21],has[N],bir[N],val[N],deep[N];vector<int>v[N];int cmp(int x,int y,int k){ if(x+k>n||y+k>n)return 0; return ran[x]==ran[y]&&ran[x+k]==ran[y+k];}void getsa(){ int i,cnt; for(i=1;i<=n;i++)has[s[i]]++; for(i=1,cnt=0;i<=128;i++)if(has[i])tr[i]=++cnt; for(i=1;i<=128;i++)has[i]+=has[i-1]; for(i=1;i<=n;i++)ran[i]=tr[s[i]],sa[has[s[i]]--]=i; for(int k=1;cnt!=n;k<<=1) { for(i=1;i<=n;i++)has[i]=0; for(i=1;i<=n;i++)has[ran[i]]++; for(i=1;i<=n;i++)has[i]+=has[i-1]; for(i=n;i>=1;i--)if(sa[i]>k)tr[sa[i]-k]=has[ran[sa[i]-k]]--; for(i=1;i<=k;i++)tr[n-i+1]=has[ran[n-i+1]]--; for(i=1;i<=n;i++)sa[tr[i]]=i; for(i=1,cnt=0;i<=n;i++)tr[sa[i]]=cmp(sa[i],sa[i-1],k) ? cnt:++cnt; for(i=1;i<=n;i++)ran[i]=tr[i]; } for(int i=1;i<=n;i++) { if(ran[i]==1)continue; for(int j=max(1,h[ran[i-1]][0]-1);;j++) { if(s[i+j-1]==s[sa[ran[i]-1]+j-1])h[ran[i]][0]=j; else break; } } for(int i=1;i<=n;i++)h[i][0]=h[i+1][0];}int rmq(int x,int y){ if(x==y)return n; if(x>y)swap(x,y);y--; int t=bir[y-x+1]; return min(h[x][t],h[y-(1<<t)+1][t]);}struct node{ int v,pos; node(){} node(int v,int pos):v(v),pos(pos){} friend bool operator < (const node &r1,const node &r2) { if(r1.v==r2.v)return r1.pos>r2.pos; return r1.v<r2.v; }; friend bool operator > (const node &r1,const node &r2) { if(r1.v==r2.v)return r1.pos<r2.pos; return r1.v>r2.v; };}bj[N<<2];struct seg_tree1{ node query(int l,int r,int now,int pos) { if(l==r)return bj[now]; int mid=(l+r)>>1; node ret=bj[now]; if(mid>=pos)return max(query(ls,pos),ret); else return max(query(rs,pos),ret); } void update(int l,int r,int now,int lq,int rq,node v) { if(lq<=l&&r<=rq) {bj[now]=max(bj[now],v);return;} int mid=(l+r)>>1; if(mid>=lq)update(ls,lq,rq,v); if(mid<rq) update(rs,lq,rq,v); }}tr1;struct seg_tree2{ int tr[N<<2]; void init(){memset(tr,0x3f,sizeof(tr));} int query(int l,int r,int now,int lq,int rq) { if(lq<=l&&r<=rq)return tr[now]; int mid=(l+r)>>1,ret=n; if(mid>=lq)ret=min(ret,query(ls,lq,rq)); if(mid<rq) ret=min(ret,query(rs,lq,rq)); return ret; } void update(int l,int r,int now,int pos,int v) { if(l==r) {tr[now]=min(tr[now],v);return;} int mid=(l+r)>>1; if(mid>=pos)update(ls,pos,v); else update(rs,pos,v); tr[now]=min(tr[now<<1],tr[now<<1|1]); }}tr2;int main(){ //freopen("tt.in","r",stdin); scanf("%d",&n);scanf("%s",s+1); getsa(); for(int i=1,j=0;i<=n;i++) { if((1<<j+1)<=i)j++; bir[i]=j; } for(int i=1;i<=20;i++) for(int j=1;j<=n;j++) if(j+(1<<i)-1<=n) h[j][i]=min(h[j][i-1],h[j+(1<<i-1)][i-1]); tr2.init(); for(int i=n;i>=1;i--) { node t=tr1.query(1,n,1,ran[i]); int l1,r1,l,r,pos; l1=1;r1=ran[i]; while(l1<=r1) { int mid=(l1+r1)>>1; if(rmq(mid,ran[i])<t.v)l1=mid+1; else r1=mid-1; } l=l1; l1=ran[i];r1=n; while(l1<=r1) { int mid=(l1+r1)>>1; if(rmq(ran[i],mid)<t.v)r1=mid-1; else l1=mid+1; } r=r1; if(t.v) { pos=tr2.query(1,n,1,l,r); val[i]=pos+t.v-i; deep[i]=deep[t.pos]+1; } else val[i]=1,deep[i]=1; tr2.update(1,n,1,ran[i],i); l1=1;r1=ran[i]; while(l1<=r1) { int mid=(l1+r1)>>1; if(rmq(mid,ran[i])<val[i])l1=mid+1; else r1=mid-1; } l=l1; l1=ran[i];r1=n; while(l1<=r1) { int mid=(l1+r1)>>1; if(rmq(ran[i],mid)<val[i])r1=mid-1; else l1=mid+1; } r=r1; tr1.update(1,n,1,l,r,node(val[i],i)); } for(int i=n;i>=1;i--) ans=max(ans,deep[i]); printf("%d\n",ans); return 0;}
0 0
- codeforces 700E 后缀数组
- Codeforces 700E Cool Slogans 后缀数组+线段树
- codeforces 452E Three strings 后缀数组+并查集
- Codeforces 452E Three strings 后缀数组 + 并查集
- 【codeforces】Codeforces Round #305 (Div. 1)E. Mike and Friends【后缀数组+线段树】
- Codeforces Round #305 (Div. 1)E. Mike and Friends 后缀数组+RMQ+线段树
- Codeforces Round #305 (Div. 1)E. Mike and Friends【后缀数组+线段树】
- 【codeforces】741E. Arpa’s abnormal DNA and Mehrdad’s deep interest【后缀数组+分块】
- Codeforces Round #422 (Div. 2) E. Liar 贪心 dp 后缀数组
- Codeforces 276E(树状数组)
- Codeforces 387E 树状数组
- codeforces 427 D Match & Catch ( 后缀数组 )
- codeforces F.Forbidden Indices后缀数组+LCP
- CodeForces 427D Match & Catch 后缀数组
- Codeforces 427D Match & Catch 后缀自动机 或 后缀数组
- CF 700E Cool Slogans 线段树+后缀数组贪心求解
- codeforces 191 E (树状数组+二分)
- Codeforces 570E,DP+滚动数组
- HDU4710
- 数据结构实验之图论二:基于邻接表的广度优先搜索遍历
- Android6.0 SystemServer进程
- 轻松安装和破解 Navicat for MySQL
- Netty
- codeforces 700E 后缀数组
- 地精排序
- Qt 自定义 滚动条 样式
- Qt学习笔记05【MainWindow 简介】
- 数据结构实验之图论七:驴友计划
- mybatis可重用方案
- Service的onStartCommand()返回的三个参数的意义
- 【C++】map的使用
- Strand Sort