[尾碼數組+二分+rmq] hdu 5008 Boring String Problem

來源:互聯網
上載者:User

標籤:io   os   ar   for   資料   div   sp   代碼   log   

有點小可惜這道題,當時整個思路都想到了,就是最後找最左下標的時候不會處理,

然後結束完發現直接暴力就可以了,想到了可是不敢寫,10w個a直接就T了啊。。。

資料太弱了,敢寫就過系列啊 T T。

然後希望有大神提供完美思路!

題意:

給一個字串 然後n次詢問
對於每一次詢問給一個v
然後問第 l⊕r⊕v+1小的子串的區間   (⊕代表異或)
然後輸出l r 
這裡的l r 就是上一次輸出的l r  初始化是0 0 
不存在輸出0 0  如果多個 輸出出現最早的。 思路:首先尾碼數組就不說了,做完之後遍曆height,沒有重複的串的話,同一sa裡面不同的長度就是排序了,小的在前。所以開一個結構體ans存三個東西,l:初始位置,r:可用的第一個位置(因為會有重複的子串),s:這個下標內有多少名。(聲明:這裡面的出現的不一定是最早的下標)所以我們先通過二分  找到它是在哪個尾碼的首碼,就是sa的下標。然後通過暴力前後,rmq判斷,找到最早出現的位置(就是這個  居然不逾時!!)
代碼:
#include"cstdlib"#include"cstdio"#include"cstring"#include"cmath"#include"stack"#include"algorithm"#include"iostream"using namespace std;#define N 300012__int64 wa[N],wb[N],wv[N],wws[N];__int64 sa[N],ra[N],v[N],height[N],used[N];__int64 Log[N],dp[N][30];char fuck[N],fu[N];struct node{    __int64 l,r,s;} ans[N];__int64 cmp(__int64 *r,__int64 a,__int64 b,__int64 l){    return r[a]==r[b]&&r[a+l]==r[b+l];}void da(__int64 n,__int64 m){    __int64 i,j,p,*x=wa,*y=wb;    for(i=0; i<m; i++) wws[i]=0;    for(i=0; i<n; i++) wws[x[i]=v[i]]++;    for(i=1; i<m; i++) wws[i]+=wws[i-1];    for(i=n-1; i>=0; i--) sa[--wws[x[i]]]=i;    for(j=1,p=1; p<n; j*=2,m=p)    {        for(i=n-j,p=0; 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<n; i++) wv[i]=x[y[i]];        for(i=0; i<m; i++) wws[i]=0;        for(i=0; i<n; i++) wws[wv[i]]++;        for(i=1; i<m; i++) wws[i]+=wws[i-1];        for(i=n-1; i>=0; i--) sa[--wws[wv[i]]]=y[i];        for(swap(x,y),p=1,i=1,x[sa[0]]=0; i<n; i++) x[sa[i]]=cmp(y,sa[i],sa[i-1],j)?p-1:p++;    }    return ;}void gethei(__int64 n){    __int64 i,j,k=0;    for(i=1; i<=n; i++) ra[sa[i]]=i;    for(i=0; i<n; i++)    {        if(k) k--;        j=sa[ra[i]-1];        while(v[i+k]==v[j+k]) k++;        height[ra[i]]=k;    }    return ;}void rmqinit(__int64 n){    __int64 i,j;    __int64 m=Log[n];    for(i=1; i<=n; i++) dp[i][0]=height[i];    for(i=1; i<=m; i++)    {        for(j=1; j+(1<<i)-1<=n; j++)            dp[j][i]=min(dp[j][i-1],dp[j+(1<<(i-1))][i-1]);    }}__int64 lcp(__int64 a,__int64 b){    __int64 x=ra[a],y=ra[b];    if(x>y) swap(x,y);    x++;    __int64 m=Log[y-x+1];    return min(dp[x][m],dp[y-(1<<m)+1][m]);}int main(){    while(scanf("%s",fuck)!=-1)    {        __int64 n;        scanf("%I64d",&n);        __int64 i;        __int64 len=strlen(fuck);        for(i=0; i<len; i++) v[i]=fuck[i]-'a'+2;        v[len]=0;        da(len+1,40);        gethei(len);        rmqinit(len);        memset(ans,0,sizeof(ans));        for(i=1; i<=len; i++)        {            ans[i].l=sa[i]; // 初始位置,原串的下標            ans[i].r=sa[i]+height[i];  //可用的第一個位置 也就是去重了            ans[i].s=len-sa[i]-height[i]+ans[i-1].s;  //  到i 已經有多少名了        }        __int64 ansl,ansr;   //輸出答案 初始化0        ansl=ansr=0;        while(n--)        {            __int64 xx;            __int64 k,sb=-1,l,r,chang;            scanf("%I64d",&xx);            k=(ansl^ansr^xx)+1;  //記得異或完加一            if(k>ans[len].s)  //如果超出 說明不存在 直接輸出            {                puts("0 0");                ansl=ansr=0;                continue;            }            l=1;            r=len;            while(l<=r)        //二分位置            {                __int64 mid=(l+r)/2;                if(ans[mid].s>=k)                {                    sb=mid;                    r=mid-1;                }                else l=mid+1;            }            ansl=ans[sb].l;            ansr=ans[sb].r+(k-ans[sb-1].s-1);            chang=ansr-ansl+1;        //[ansl,ansr]就是子串了 但不一定是最早的,同時記錄長度            __int64 x;            x=sb-1;  //向前遍曆            while(x>=2 && lcp(sa[sb],sa[x])>=chang)            {                ansl=min(ansl,ans[x].l);  //記錄最小                x--;            }            x=sb+1;  //向後遍曆            while(x<=len && lcp(sa[sb],sa[x])>=chang)            {                ansl=min(ansl,ans[x].l);  //記錄最小                x++;            }            ansl=ansl+1;            ansr=ansl+chang-1;            printf("%I64d %I64d\n",ansl,ansr);        }    }    return 0;}




[尾碼數組+二分+rmq] hdu 5008 Boring String Problem

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.