您的位置:首页 > 理论基础 > 计算机网络

后缀数组(2014西安网络赛)hdu5008

2014-09-14 19:38 441 查看




Online Judge
Online Exercise
Online Teaching
Online Contests
Exercise Author

F.A.Q

Hand In Hand

Online Acmers

Forum | Discuss

Statistical Charts

Problem Archive

Realtime Judge Status

Authors Ranklist



C/C++/Java Exams

ACM Steps

Go to Job

Contest LiveCast

ICPC@China

Best Coder beta

VIP | STD
Contests

Virtual Contests

DIY | Web-DIY beta

Recent Contests





Author ID

Password

Register
new ID

BestCoder官方群:385386683 欢迎加入~
寻人启事:2014级新生看过来!

Boring String Problem

Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 97 Accepted Submission(s): 10



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

aaa
4
0
2
3
5




Sample Output

1 1
1 3
1 2
0 0


最后一点时间来做这个题,知道是后缀数组可以做,当时没有想出来怎么解救位置的问题

就像aaa,这样求完后缀数组后

2 a

1 aa

0 aaa

这样找位置的时候会找到2,2,于是还没想到时间就到了。。。

比赛结束之后看了一下,其实只需要从当前位置再往下找就行,只要保存下最小的位置就行

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=100010;
typedef long long LL;
int sa[maxn],height[maxn],rank[maxn],t[maxn],t2[maxn],c[maxn];
int n;
char str[maxn];

void build_sa(int m,int n)
{
    int *x=t,*y=t2;
    for(int i=0;i<m;i++)c[i]=0;
    for(int i=0;i<n;i++)c[x[i]=str[i]]++;
    for(int i=1;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[y[i]]]++;
        for(int i=1;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);
        x[sa[0]]=0;p=1;
        for(int i=1;i<n;i++)
            x[sa[i]]=(y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++);
        if(p>=n)break;
        m=p;
    }
}

void getheight(int n)
{
    int k=0;
    for(int i=1;i<=n;i++)rank[sa[i]]=i;
    for(int i=0;i<n;i++)
    {
        if(k)k--;
        int j=sa[rank[i]-1];
        while(str[i+k]==str[j+k])k++;
        height[rank[i]]=k;
    }
}
int q;
LL sum[maxn];
void process()
{
    memset(sum,0,sizeof(sum));
    sum[1]=n-sa[1];
    for(int i=2;i<=n;i++)
        sum[i]=sum[i-1]+n-sa[i]-height[i];
}
void solve()
{
    scanf("%d",&q);
    LL l=0,r=0;
    process();
    while(q--)
    {
        LL v;
        scanf("%I64d",&v);
        LL k=(l^r^v)+1;
        int pos=lower_bound(sum+1,sum+1+n,k)-sum;
        LL tl=sa[pos],tr=n-(sum[pos]-k+1);
        l=tl,r=tr;
        int len=tr-tl+1;
        while(pos+1<=n&&height[pos+1]>=len)
        {
            pos++;
            tl=sa[pos],tr=tl+len-1;
            l=min(l,tl),r=min(r,tr);
        }
        l++,r++;
        if(pos>=n+1)l=r=0;
        cout<<l<<" "<<r<<endl;
    }
}
int main()
{
    while(scanf("%s",str)!=EOF)
    {
        n=strlen(str);
        build_sa(123,n+1);
        getheight(n);
        solve();
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: