hdu 5008 Boring String Problem
来源:互联网 发布:网络直播第一人 编辑:程序博客网 时间:2024/04/27 18:36
Boring String Problem
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 291 Accepted Submission(s): 71
Problem Description
In this problem, you are given a string s and q queries.
For each query, you should answer that when all distinct substrings of string s were sorted lexicographically, which one is the k-th smallest.
A substring si...j of the string s = a1a2 ...an(1 ≤ i ≤ j ≤ n) is the string aiai+1 ...aj. Two substrings sx...y and sz...w are cosidered to be distinct if sx...y ≠ Sz...w
For each query, you should answer that when all distinct substrings of string s were sorted lexicographically, which one is the k-th smallest.
A substring si...j of the string s = a1a2 ...an(1 ≤ i ≤ j ≤ n) is the string aiai+1 ...aj. Two substrings sx...y and sz...w are cosidered to be distinct if sx...y ≠ Sz...w
Input
The input consists of multiple test cases.Please process till EOF.
Each test case begins with a line containing a string s(|s| ≤ 105) with only lowercase letters.
Next line contains a postive integer q(1 ≤ q ≤ 105), the number of questions.
q queries are given in the next q lines. Every line contains an integer v. You should calculate the k by k = (l⊕r⊕v)+1(l, r is the output of previous question, at the beginning of each case l = r = 0, 0 < k < 263, “⊕” denotes exclusive or)
Each test case begins with a line containing a string s(|s| ≤ 105) with only lowercase letters.
Next line contains a postive integer q(1 ≤ q ≤ 105), the number of questions.
q queries are given in the next q lines. Every line contains an integer v. You should calculate the k by k = (l⊕r⊕v)+1(l, r is the output of previous question, at the beginning of each case l = r = 0, 0 < k < 263, “⊕” denotes exclusive or)
Output
For each test case, output consists of q lines, the i-th line contains two integers l, r which is the answer to the i-th query. (The answer l,r satisfies that sl...r is the k-th smallest and if there are several l,r available, ouput l,r which with the smallest l. If there is no l,r satisfied, output “0 0”. Note that s1...n is the whole string)
Sample Input
aaa40235
Sample Output
1 11 31 20 0
这道题目求有多少不同的子串,在我的blog里有原题,以及怎么height数组为什么可以二分查找,我之前做过的题也有解释,可以参考我的后缀数组这块。虽然刷过不少的后缀数组题,但是真正的比赛还是写不出来啊,看来水平远远不够。注意一下,网上的题解有些没有二分查找下标最靠左的,这样其实会超时的,测试数据可能水了些吧。
比如全a的话,如果要查排名第1的位置,那么不得查到最后一个,这样显然超时,测试数据应该给出这样的例子,这题还要注意long long,被坑了好多次。
代码:
#include<cstdio>#include<iostream>#include<cstring>#define Maxn 100010#define ll long longusing namespace std;char s[Maxn];int r[Maxn],sa[Maxn],rk[Maxn],height[Maxn];int wa[Maxn],wb[Maxn],rs[Maxn],wv[Maxn];ll a,b,k,v;int cmp(int *r,int a,int b,int l){ return r[a]==r[b]&&r[a+l]==r[b+l];}void da(int n,int m){ int i,j,p,*x=wa,*y=wb; for(i=0;i<m;i++) rs[i]=0; for(i=0;i<n;i++) rs[x[i]=r[i]]++; for(i=1;i<m;i++) rs[i]+=rs[i-1]; for(i=n-1;i>=0;i--) sa[--rs[x[i]]]=i; for(j=1,p=1;p<n;j<<=1,m=p){ for(p=0,i=n-j;i<n;i++) y[p++]=i; for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j; for(i=0;i<m;i++) rs[i]=0; for(i=0;i<n;i++) rs[wv[i]=x[y[i]]]++; for(i=1;i<m;i++) rs[i]+=rs[i-1]; for(i=n-1;i>=0;i--) sa[--rs[wv[i]]]=y[i]; swap(x,y); for(p=1,x[sa[0]]=0,i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; }}void calheight(int n){ int i,j,k=0; for(int i=1;i<n;i++) rk[sa[i]]=i; for(int i=1;i<n;height[rk[i++]]=k){ if(k) k--; for(j=sa[rk[i]-1];r[i+k]==r[j+k];k++); }}int p[Maxn];ll d[Maxn][20],d1[Maxn][20],sum[Maxn];void rmq_init(int n,int *height,ll (*d)[20]){ p[0]=-1; for(int i=1;i<=n;i++) p[i]=i&i-1?p[i-1]:p[i-1]+1; for(int i=1;i<=n;i++) d[i][0]=height[i]; for(int j=1;j<=p[n];j++) for(int i=1;i+(1<<j)-1<=n;i++) d[i][j]=min(d[i][j-1],d[i+(1<<j-1)][j-1]);}ll rmq_ask(int l,int r,ll (*d)[20]){ int k=p[r-l+1]; return min(d[l][k],d[r-(1<<k)+1][k]);}ll lcp(int a,int b){ if(a<b) swap(a,b); return rmq_ask(b+1,a,d);}int b_search1(int l,int r,ll k){ while(l<r){ int mid=l+r+1>>1; if(sum[mid]<k) l=mid; else r=mid-1; } return l;}ll b_search2(int s,int l,int r,ll k){ while(l<r){ int mid=l+r+1>>1; if(lcp(s,mid)<k) r=mid-1; else l=mid; } if(lcp(s,l)>=k) return rmq_ask(s,l,d1); return a;}int main(){ int i,t,n; while(~scanf("%s",s+1)){ for(i=1;s[i];i++) r[i]=s[i]-'a'+1; r[0]=r[n=i]=sum[0]=0; da(n,27); calheight(n); for(i=1;i<n;i++) sum[i]=n-sa[i]-height[i]; for(i=1;i<n;i++) sum[i]+=sum[i-1]; rmq_init(n,height,d); rmq_init(n,sa,d1); a=b=0; scanf("%d",&t); while(t--){ scanf("%I64d",&v); k=(a^b^v)+1; if(k<=sum[n-1]){ int id=b_search1(0,n-1,k)+1; a=sa[id]; a=min(a,b_search2(id,id+1,n-1,k-sum[id-1]+height[id])); b=a+k-sum[id-1]+height[id]-1; } else a=b=0; printf("%I64d %I64d\n",a,b); } }return 0;}
0 0
- hdu 5008 Boring String Problem
- hdu 5008 Boring String Problem
- hdu 5008 Boring String Problem(后缀数组)
- HDU 5008 Boring String Problem 后缀数组
- hdu 5008 Boring String Problem(后缀数组)
- hdu 5008 Boring String Problem 【后缀数组】
- hdu 5008 Boring String Problem 后缀数组
- HDU 5008 Boring String Problem 后缀数组
- HDU 5008 Boring String Problem 后缀数组 RMQ
- [后缀数组+二分+rmq] hdu 5008 Boring String Problem
- hdu 5008 Boring String Problem(后缀自动机构造后缀树)
- HDU - 5008 Boring String Problem (后缀数组+二分+RMQ)
- HDU 5008 B - Boring String Problem(非常好的题目)
- HDU 5008 Boring String Problem 二分 + 后缀数组
- HDOJ 5008 Boring String Problem
- 【后缀数组】 HDOJ 5008 Boring String Problem
- Boring String Problem
- hdu 5008(2014 ACM/ICPC Asia Regional Xi'an Online ) Boring String Problem(后缀数组&二分)
- 黑马程序员——从键盘接受一个数字,打印该数字表示的时间,最大单位到天
- 《数据结构》第一章 绪论 知识结构导图——信管1133-09
- Win7专业版添加管理员
- String intern的深入理解(转)
- 黑马程序员——定义一个二维int数组,编写代码获取最小元素
- hdu 5008 Boring String Problem
- java开源思想
- java 多线程(转)
- BitmapImage 获取网络图片,Width和Height都为1的解决办法。
- 大一暑期总结
- 黑马程序员——第4题: 以下代码哪个是正确的?为什么?
- 广告学(一)
- 黑马程序员——编写程序接收键盘输入的5个数,装入一个数组,并找出其最大数和最小数
- 快速排序