HDU 5008 Boring String Problem(后缀数组+二分)

题目链接

思路 想到了,但是木写对啊....代码 各种bug,写的乱死了....

输出最靠前的,比较折腾...

#include <cstdio>

#include <cstring>

#include <algorithm>

#include <iostream>

#include <cmath>

#include <map>

using namespace std;

#define N 501000

#define LL __int64

int sa[N],height[N],rank[N];

int c[N],wa[N],wb[N];

int p[N];

int res[N];

char str[N];

LL sum[N];

LL l,r;

int bin[31];

int minz[22][N];

int sz[22][N];

void build_sa(int s[],int n,int m)

{

    int i,j,p,*x = wa,*y = wb;

    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 >= 0;i --)

    sa[--c[x[i]]] = i;

    for(j = 1;j <= n;j <<= 1)

    {

        p = 0;

        for(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 ++)

        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 >= 0;i --)

        sa[--c[x[y[i]]]] = y[i];

        swap(x,y);

        p = 1;x[sa[0]] = 0;

        for(i = 1;i < n;i ++)

        x[sa[i]] = y[sa[i-1]] == y[sa[i]]&&y[sa[i-1]+j] == y[sa[i]+j]?p-1:p++;

        if(p >= n) break;

        m = p;

    }

}

void get_height(int s[],int n)

{

    int i,j,k = 0;

    for(i = 1;i <= n;i ++)

    rank[sa[i]] = i;

    for(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;

    }

}

void init(int n)

{

    int i,j;

    for(i = 1; i <= n; i ++)

    {

        minz[0][i] = height[i];

        sz[0][i] = sa[i];

    }

    for(i = 1; bin[i] <= n; i ++)

    {

        for(j = 1; j + bin[i-1] <= n; j ++)

        {

            minz[i][j] = min(minz[i-1][j],minz[i-1][j+bin[i-1]]);

            sz[i][j] = min(sz[i-1][j],sz[i-1][j+bin[i-1]]);

        }

    }

}

int rmq(int s,int t)

{

    s = rank[s];

    t = rank[t];

    if(s > t) swap(s,t);

    s ++;

    int k = log((t-s+1)*1.0)/log(2.0);

    return min(minz[k][s],minz[k][t-bin[k]+1]);

}

int rmq1(int s,int t)

{

    s = rank[s];

    t = rank[t];

    if(s > t) swap(s,t);

    s ++;

    int k = log((t-s+1)*1.0)/log(2.0);

    return min(sz[k][s],sz[k][t-bin[k]+1]);

}

void find(LL k,int n)

{

    int str,end,mid,i;

    str = 1;

    end = n;

    while(str < end)

    {

        mid = (str + end + 1)/2;

        if(sum[mid] > k)

        end = mid - 1;

        else

        str = mid;

    }

    i = end;

    if(sum[end] > k)

    {

        l = sa[i];

        r = sa[i]+k-1;

    }

    else if(k == sum[end])

    {

        l = sa[i];

        r = n-1;

    }

    else

    {

        i ++;

        l = sa[i];

        r = sa[i]  + k - sum[end] + height[i]-1;

    }

    int len = r-l+1;

    if(i == n)

    {

        l ++;

        r ++;

        return ;

    }

    if(height[i+1] < len)

    {

        l ++;

        r ++;

        return ;

    }

    str = i+1;

    end = n;

    while(str < end)

    {

        mid = (str + end + 1)/2;

        if(rmq(sa[i],sa[mid]) < len)

        end = mid - 1;

        else

        str = mid;

    }

    if(rmq(sa[i],sa[end]) >= len)

    {

        l = min(l,(LL)rmq1(sa[i],sa[end]));

        r = l+len-1;

    }

    l ++;

    r ++;

}

int main()

{

    int i,len,n;

    LL maxz;

    for(i = 0; i < 21; i ++)

        bin[i] = 1<<i;

    LL v,k;

    while(scanf("%s",str)!=EOF)

    {

        len = strlen(str);

        for(i = 0;i < len;i ++)

        {

            p[i] = str[i]-'a'+1;

        }

        p[len] = 0;

        build_sa(p,len+1,30);

        get_height(p,len);

        init(len);

        maxz = 0;

        for(i = 1;i  <= len;i ++)

        {

            maxz += len-sa[i]-height[i];

            sum[i] = maxz;

        }

        scanf("%d",&n);

        l = r = 0;

        for(i = 0;i < n;i ++)

        {

            scanf("%I64d",&v);

//            find(v,len);

//            printf("%I64d %I64d\n",l,r);

             k = (v^l^r)+1;



            if(k > maxz)

            {

                l = r = 0;

            }

            else

            {

                find(k,len);

            }

            printf("%I64d %I64d\n",l,r);

        }

    }

    return 0;

}
View Code

 

你可能感兴趣的:(String)