首页 > 代码库 > HDU 5008 Boring String Problem(后缀数组+二分)

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 __int64int 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(后缀数组+二分)