HDU 4416 Good Article Good sentence(尾碼數組 求在只在某串中出現的子串數目)

來源:互聯網
上載者:User

題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=4416

這個題目我感覺不好寫,各種出錯,最後參考這篇部落格的程式和思想才得以完成:http://hi.baidu.com/arosliu/item/ec421c23bf862ef951fd8769

開始按照以前的尾碼數組的寫法,老是Run time error 後來改成上面連結的尾碼數組寫法就沒問題了,目前還不知道問題出在什麼地方

這個題目的思想我覺得非常巧妙,很好的利用了尾碼數組和height數組的性質

首先處理這種多個字串問題一般要是用尾碼數組來處理的話就是字串拼接,拼接的同時在每個串之間插入一個獨一無二的字元

所以這裡在處理的時候把字元全部轉換成整形數,原因是如果用字元,哪來那麼多獨一無二的字元呢

然後拼接完成之後求sa rank 和height,然後求出這個數組的所有不用子串的數目,這個數目還是比較好求的

求完之後減去子串中包含特殊字元(我們拼接時候添加的)的子串數目,現在得出的結果就是不包含特殊字元的不同子串的個數

實際上就所有串中不同子串的數目(這裡好好理解下),因為前面加後面的總共是len_ab,後面的是len_b,結果肯定是相減嘛

同樣的做法求出後面,也就是不包含第一個串的這個值,然後兩個相減就得到了結果!

至於怎樣求解包含特殊字元的不同字串個數呢,其實就是下面這段代碼

 for (i = 0; i < number; i++)
        {
            l -= L[i];
            len_ab-= (L[i]+1)*l;
            l--;
        }

L[i]表示第i個字串的長度,L初始值等於len-1;

每次都這樣減去,為什麼這樣是正確的,因為包含了這個特殊字元,那麼不同的子串個數就是個組合,前面取連續的不同的L[i]+1個,後面連續的

不同的l個,兩者相乘,當然這個只是包含第i個特殊字元的情況,隨著i++的進行,結果就出來了!

/*4416*/#include <iostream>#include <stdio.h>#include <algorithm>#include <math.h>#include <string.h>using namespace std;#define maxn 310000int top[maxn],tmp[maxn];int len;char rec[maxn];int rec1[maxn];int L[maxn];int sa[maxn];int rank[maxn],height[maxn];int *str;void makesa(){    int lena = len < 256 ? 256 : len;    memset(top, 0, lena*sizeof(int));    for (int i = 0; i < len; i++)        top[rank[i] = str[i]&(-1)]++;    for (int i = 1; i < lena; i++)        top[i] += top[i-1];    for (int i = 0; i < len ; i++)        sa[--top[rank[i]]] = i;    for (int k = 1; k < len; k <<= 1)    {        for (int i = 0; i < len; i++)        {            int j = sa[i]-k;            if (j < 0)                j += len;            tmp[top[rank[j]]++] = j;        }        int j = sa[tmp[0]] = top[0] = 0;        for (int i = 1; i < len; i++)        {            if (rank[tmp[i]] != rank[tmp[i-1]] || rank[tmp[i]+k] != rank[tmp[i-1]+k])                top[++j] = i;            sa[tmp[i]] = j;        }        memcpy(rank, sa , len*sizeof(int));        memcpy(sa , tmp, len*sizeof(int));        if (j+1 >= len)            break;    }}void lcp(){    height[0] = 0;    for (int i = 0, k = 0, j = rank[0]; i+1 < len; i++, k++)        while (k >= 0 && str[i] != str[sa[j-1]+k])        {            height[j] = k--;            j = rank[sa[j]+1];        }}int main(){    int i,j,k=0;    int left,right;    int mid,number,ans,ans1,len_f;    long long  len_ab,len_b,l;    int t;    scanf("%d",&t);    while(t--)    {        len_ab=len_b=0;        scanf("%d",&number);        scanf("%s",rec);        for(len=0;rec[len];len++)        {            rec1[len]=rec[len]-'a'+1;        }        L[0]=len;        for(i=1;i<=number;i++)        {            rec1[len++]=26+i;            scanf("%s",rec);            for(j=0;rec[j];j++)            rec1[len++]=rec[j]-'a'+1;            L[i]=j;        }        rec1[len++]=0;        str=rec1;        makesa();        lcp();          for ( i = 1; i < len; i++)            len_ab += len-1-sa[i]-height[i];        l=len-1;        for (i = 0; i < number; i++)        {            l -= L[i];            len_ab-= (L[i]+1)*l;            l--;        }        len-=L[0]+1;        str=rec1+L[0]+1;        makesa();        lcp();        for(i = 1; i < len; i++)            len_b += len-1-sa[i]-height[i];        l=len-1;        for (i = 1; i < number; i++)        {            l -= L[i];            len_b-= (L[i]+1)*l;            l--;        }        cout<<"Case "<<++k<<": "<<len_ab-len_b<<endl;        }    return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.