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
 

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)
 

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
 

一道很好的后缀数组题目,比赛时意识到了这题会用后缀数组,但是一时有没想到如何查找第k大下标最靠左的位置。比赛完后,才知道可以二分查找。

这道题目求有多少不同的子串,在我的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
原创粉丝点击