[bzoj4453]cys就是要拿英魂!
2016-04-19 09:19
239 查看
4453: cys就是要拿英魂!
Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 66 Solved: 33
[Submit][Status][Discuss]
Description
pps又开始dota视频直播了!
一群每天被pps虐的蒟蒻决定学习pps的操作技术,他们把pps在这局放的技能记录了下来,每个技能用一个字符表示。经过研究,蒟蒻们发现字典序更大的连招威力更大。于是所有蒟蒻都想学习pps最强的连招。但是他们太弱了,不能学会整个视频里的连招,只能学会陈老师一段区间间内的连招,可是这个他们求不出,于是只好向你求助。为了蒟蒻们不再被pps虐(怎么可能),请你帮帮他们。
简化题意:
给你一个字符串,每次询问你一段区间的字典序最大的子串。
Input
第一行是一个字符串S,表示pps放的技能
第二行一个正整数Q,表示询问个数
接下来Q行,每行两个正整数[l,r],表示询问区间[l,r]中的字典序最大的子串。
Output
Q行,每行一个正整数,表示该区间内字典序最大的子串的起始位置。
Sample Input
Lets_go_mod_p! 5 2 2 3 3 2 5 1 10 2 9
Sample Output
2 3 3 3 3
数据范围:
1<=|S|<=100000 1<=Q<=100000 1<=l<=r<=|S|
首先可以看出来,如果对于一个区间[l,r]有两个后缀i,j他们呢个更优可以分这么几种情况来讨论(假设i<j):
①:如果rank[i]>rank[j],那么i肯定比j优。
②:如果rank[i]<rank[j]&&lcp(i,j)<r−j+1,那么j肯定比i优。
③:如果rank[i]<rank[j]&&lcp(i,j)>=r−j+1,那么i比j更优。
这样如果从后往前扫左端点的话,那么后面的区间就会被分成一块一块的,每一块内的最优值都是一样的,也就是说一个最优值影响的区间是连续的。(也就是当固定了左端点后右端点是单调的。)
每次新扫到一个左端点后,就可以看一下这个左端点影响到了后面哪一段区间。在影响的区间打上标记。
我刚开始本来想二分后面的区间,打标记的时候给线段树区间染色,这样是O(nlog2n)的。
可以维护一个栈,栈中的每一个元素对应了一段区间。每次扫到一个左端点后,依次弹出栈顶元素,知道当前这个左端点不会影响到当前栈顶的这个区间了。
还有种情况是可能会影响到最后那个区间的一部分,这样需要在这个区间中二分一下这个区间从哪裂开。
时间复杂度是O(nlogn)的。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=100010; char s ; struct Q{int x,y,No;}q ; struct S{int v,l,r,No;}stack ; int n,m,T,top,t1 ,t2 ,c ,sa ,rank ,height ,st [20],Log ,ans ; inline int in(){ int x=0;char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x; } inline bool cmp(int *y,int p,int q,int k){ int o0,o1; o0=p+k>=n?-1:y[p+k]; o1=q+k>=n?-1:y[q+k]; return o0==o1&&y[p]==y[q]; } inline void build_sa(){ int i,k,p,*x=t1,*y=t2; for(i=0;i<m;++i) c[i]=0; for(i=0;i<n;++i) ++c[x[i]=s[i]]; for(i=1;i<m;++i) c[i]+=c[i-1]; for(i=n-1;~i;--i) sa[--c[x[i]]]=i; for(k=1;k<=n;k<<=1){ for(p=0,i=n-k;i<n;++i) y[p++]=i; for(i=0;i<n;++i) if(sa[i]>=k) y[p++]=sa[i]-k; for(i=0;i<m;++i) c[i]=0; for(i=0;i<n;++i) ++c[x[y[i]]]; for(i=1;i<m;++i) c[i]+=c[i-1]; for(i=n-1;~i;--i) sa[--c[x[y[i]]]]=y[i]; swap(x,y); x[sa[0]]=0;m=1; for(i=1;i<n;++i) x[sa[i]]=cmp(y,sa[i],sa[i-1],k)?m-1:m++; if(m>=n) break; } } inline void build_height(){ int i,k=0,j; for(i=0;i<n;++i) rank[sa[i]]=i; for(i=0;i<n;++i){ if(!rank[i]) continue; k=k?--k:k; j=sa[rank[i]-1]; while(s[j+k]==s[i+k]) ++k; height[rank[i]]=k; } memset(st,127/3,sizeof(st)); for(i=0;i<n;++i) st[i][0]=height[i]; for(j=1;j<=20;++j) for(i=0;i+(1<<(j-1))<n;++i) st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]); for(j=0,i=1;i<=n;++i){ if((1<<(j+1))<=i) ++j; Log[i]=j; } } inline int LCP(int x,int y){ if(x>y) swap(x,y); int k=Log[y-x];++x; return min(st[x][k],st[y-(1<<k)+1][k]); } inline bool CMP(Q x,Q y){return x.x>y.x;} #define mid (l+r)/2 inline bool check(int x,int y,int z){ if(rank[x]>rank[y]) return true; int len=LCP(rank[x],rank[y]); if(len<z-y+1) return false; return true; } int main(){ int i,j; scanf("%s",s); n=strlen(s); for(i=0;i<n;++i) m=max(m,(int)s[i]); ++m;build_sa(); build_height(); T=in(); for(i=1;i<=T;++i) q[i].x=in()-1,q[i].y=in()-1,q[i].No=i; sort(q+1,q+T+1,CMP); stack[0].l=n;stack[top=1].v=rank[n-1]; stack[top].No=stack[top].l=stack[top].r=n-1; for(j=1;q[j].x==n-1;++j) ans[q[j].No]=n; for(i=n-2;~i&&j<=T;--i){ int now=top,l,r,flag=0; for(;top;--top){ l=check(i,stack[top].No,stack[top].l); r=check(i,stack[top].No,stack[top].r); if(l&&r) continue; if(!l&&!r) break; if(l&&!r){ flag=1; break; } } if(flag){ now=l=stack[top].l;r=stack[top].r; while(l<r){ if(check(i,stack[top].No,mid)) now=max(now,mid),l=mid+1; else r=mid; } stack[top].l=now+1; stack[++top].v=rank[i]; stack[top].r=now; stack[top].l=stack[top].No=i; } else{ stack[++top].v=rank[i]; stack[top].No=stack[top].l=i; stack[top].r=stack[top-1].l-1; } while(q[j].x==i&&j<=T){ l=1;r=top;now=q[j].y; while(l<r){ if(now>=stack[mid].l&&now<=stack[mid].r) break; if(now<stack[mid].l) l=mid+1; else r=mid; } ans[q[j].No]=stack[mid].No+1; ++j; } } for(i=1;i<=T;++i) printf("%d\n",ans[i]); }
相关文章推荐
- 服务器中很多的CLOSE_WAIT
- SQL优化
- css样式文件命名规范
- iOS线程间通信
- 日志那点事儿——slf4j源码剖析
- css样式文件命名规范
- java毕向东听课笔记18(字符串2)
- 稳定性测试浅谈
- Kafka 协议实现中的内存优化
- HelloChart--LineChartView(折线图)
- 可扩展的调整数
- OpenCV--How to scan images, lookup tables and time measurement with OpenCV
- ASP.NET C# MD5加密 解密
- unity3d射线
- 看了这篇文章,Java编程速度我都惊呆了
- 容斥原理
- Android Weekly #201 中文版
- 学习java script的项目总结
- [转]Form Builder:app_field.clear_dependent_fields和APP_FIELD.set_dependent_field的用法
- mysql存储过程详解