codeforces 700E 后缀数组
2016-08-20 13:39
656 查看
题意:定义a串比b串优当且仅当a串中至少包含两个b串(可以重叠),给出一个串w,求一个最长的由w的子串构成的序列,满足第i个串比第i-1个串优。
题解后缀自动机没看懂,看了评论中的一个后缀数组做法。
定义一个串是好串当该串长度为1或该串的前缀和后缀都有同一个好串且该好串不出现在该串中间。
那么对于每一个后缀取一个最长的是后缀前缀的好串,最终答案一定由这些好串组成。
从n到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|1 int n,ans; char s ; int tr ,ran ,sa ,h [21],has ,bir ,val ,deep ; vector<int>v ; 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; }
相关文章推荐
- BJ 集训测试11 level&& codeforces 700E
- Codeforces 427D Match & Catch 后缀自动机 或 后缀数组
- Codeforces 700E Cool Slogans 后缀数组+线段树
- CodeForces 873F Forbidden Indices 后缀数组
- CodeForces 427D Match & Catch 后缀数组
- CodeForces 427 D.Match & Catch(后缀数组)
- codeforces 432D D . Prefixes and Suffixes(后缀数组)
- Codeforces 700E. Cool Slogans
- codeforces 873F(后缀数组)
- Codeforces 700E Cool Slogans 后缀自动机+可持久化线段树+dp
- Codeforces 504E Misha and LCP on Tree 树链剖分+后缀数组
- 【线段树】 Codeforces 500E New Year Domino
- codeforces 615B Longtail Hedgehog
- 分解质因数之codeforces_588B
- CodeForces - 701C They Are Everywhere (尺取法)
- CodeForces 815E Karen and Neighborhood题解
- codeforces 894B. Ralph And His Magic Field (数学题+思维)
- Codeforces 149D Coloring Brackets(区间dp)
- Codeforces 617D Polyline 【枚举】
- CodeForces 427A Police Recruits