码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2014-09-14 20:31:07      阅读:233      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   io   os   ar   for   art   

题目链接

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

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

bubuko.com,布布扣
#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

 

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

标签:style   blog   http   color   io   os   ar   for   art   

原文地址:http://www.cnblogs.com/naix-x/p/3971407.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!