BZOJ 4556 [HEOI 2016] str
来源:互联网 发布:win7恢复网络设置方法 编辑:程序博客网 时间:2024/06/06 18:49
学习了一下经典的在后缀数组上维护主席树的思想。
求出sa和height数组,以sa数组对原串建主席树,对每个询问二分答案出长度ans,然后只要在(c,c+len)的区间中查找是否有属于(a,b-len+1)的下标。
出了几个小问题查了好久。
开始用的cmath 里的log函数求RMQ 直接爆炸,还是自己手打吧。
小样例全过了但交上去WA了,发现自己RMQ的st数组…st[maxn][20]…
maxn和20居然写反了。。。我说咋老RE…
#include<cstdio>#include<iostream>#include<cstring>#include<cmath>using namespace std;const int maxn=103010;int c[maxn],t1[maxn],t2[maxn],sa[maxn],height[maxn],root[maxn],rank[maxn],cnt,n,m,st[20][maxn],lg[maxn];char s[maxn];void build_sa(int m){ int *x=t1,*y=t2; for(int i=0;i<m;i++) c[i]=0; for(int i=0;i<n;i++) c[x[i]=s[i]]++; for(int i=0;i<m;i++) c[i]+=c[i-1]; for(int i=n-1;i>=0;i--) sa[--c[x[i]]]=i; for(int k=1;k<=n;k<<=1) { int p=0; for(int i=n-k;i<n;i++) y[p++]=i; for(int i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k; for(int i=0;i<m;i++) c[i]=0; for(int i=0;i<n;i++) c[x[i]]++; for(int i=0;i<m;i++) c[i]+=c[i-1]; for(int i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i]; swap(x,y); p=1,x[sa[0]]=0; for(int i=1;i<n;i++) x[sa[i]]= y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k] ? p-1 : p++; if(p>=n) break; m=p; } }void get_height(){ int j,k=0; for(int i=1;i<=n;i++) rank[sa[i]]=i; for(int i=0;i<n;i++) { if(k) k--; j=sa[rank[i]-1]; while(s[i+k]==s[j+k]) k++; height[rank[i]]=k; }}struct node{ int l,r,sum;};node T[maxn*40];void update(int l,int r,int &x,int &y,int pos){ x=++cnt;T[x]=T[y];T[x].sum++; int mid=(l+r)>>1; if(l==r) return ; if(pos<=mid) update(l,mid,T[x].l,T[y].l,pos); else update(mid+1,r,T[x].r,T[y].r,pos);} int query(int l,int r,int x,int y,int L,int R){ if(L<=l&&r<=R) return T[y].sum-T[x].sum; int ans=0; int mid=(l+r)>>1; if(L<=mid) ans=query(l,mid,T[x].l,T[y].l,L,R); if(R>mid) ans+=query(mid+1,r,T[x].r,T[y].r,L,R); return ans;}void St() { for(int i=1;i<=n;i++) st[0][i] = height[i]; for(int j=1;j<18;j++) for(int i = n-(1<<j)+1; i > 0; -- i) st[j][i] = min(st[j-1][i], st[j-1][i+(1<<j-1)]);}int a1,b1,c1,d1;int main(){ freopen("heoi2016_str.in","r",stdin); freopen("heoi2016_str.out","w",stdout); scanf("%d%d",&n,&m); scanf("%s",s);n++; build_sa(200);n--; get_height();St(); for(int i=1;i<=n;i++) update(1,n,root[i],root[i-1],sa[i]+1); for(int i=2;i<=n;i++) lg[i] = lg[i>>1] + 1; for(int i = 1; i <= m; ++ i) { scanf("%d%d%d%d",&a1,&b1,&c1,&d1); int l=1,r=min(d1-c1+1, b1-a1+1), mid, ans = 0; while(l <= r) { int mid=l+r>>1; int lp = rank[c1-1], rp = lp; for(int k=lg[n];k>=0;k--) { if(lp>=(1<<k)&&st[k][lp-(1<<k)+1]>=mid) lp -= 1<<k; if(rp<=n-(1<<k)&&st[k][rp+1] >= mid) rp += 1<<k; } if(query(1,n,root[lp-1],root[rp],a1,b1-mid+1)>0) ans = mid, l = mid+1; else r = mid-1; } printf("%d\n", ans); } return 0;}
0 0
- BZOJ 4556 [HEOI 2016] str
- BZOJ 4553 HEOI 2016 seq
- 【TJOI & HEOI 2016】【BZOJ 4556】【JZOJ 4614】 游戏
- BZOJ 4868 HEOI 期末考试
- 【TJOI & HEOI 2016】【JZOJ 4604】【BZOJ 4551】 树
- 【TJOI & HEOI 2016】【JZOJ 4605】 【BZOJ 4552】排序
- 【TJOI & HEOI 2016】【BZOJ 4554】【JZOJ 4612】 游戏
- BZOJ 4551 HEOI 2016 树 (并查集)
- BZOJ 2743 HEOI 2012 采花 树状数组
- [bzoj 3611] [heoi 2014] 大工程
- BZOJ 4870 HEOI 2017 组合数问题
- COGS 2274. [HEOI 2016] tree
- HEOI-2012 DAY1 题解 (BZOJ 2742-2744)
- BZOJ 3611 HEOI 2014 大工程 LCA单调性
- BZOJ 3613 HEOI 2014 南园满地堆轻絮 二分+贪心
- [BZOJ 1120]POI2009 str
- BZOJ 1120: [POI2009]STR
- BZOJ 2744 [HEOI 2012] 二分图最大独立集 解题报告
- Quick Sort and Random Quick Sort
- JSTREE生成树
- LeetCode Summary Sort
- 寒假学习之stm32(15)----DMA(direct memory access)
- Java中文转Unicode码
- BZOJ 4556 [HEOI 2016] str
- android文本框左右加减按钮长按一直加减
- mysql 减少group by 的开销
- JQery实现Checkbox至少保证有一个选中
- LeetCode Summary STL Stack Queue
- 关于BFS的小节
- 朴素贝叶斯
- 安装 JDK
- 最短的名字