• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            Tim's Programming Space  
            Tim's Programming Space
            日歷
            <2010年4月>
            28293031123
            45678910
            11121314151617
            18192021222324
            2526272829301
            2345678
            統(tǒng)計
            • 隨筆 - 20
            • 文章 - 1
            • 評論 - 40
            • 引用 - 0

            導航

            常用鏈接

            留言簿(3)

            隨筆檔案

            文章檔案

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

             
            前兩天在yjw神牛和hyf神牛的共同努力下終于學會了后綴數(shù)組O(nlogn)倍增構(gòu)造方法。

            構(gòu)造:
            定義s[k][i]表示從s字符串的第i位開始的長度為k的一個字符串(后綴),不夠的補零,sa[k][i]表示在所有長度為k的后綴中排序后大小為第i的后綴的位置。顯然sa[1]可以直接qsort得到。當sa[k]求到過后,sa[2k]的每個元素都可以O(shè)(1)比較得出,這時用桶排,把sa[k]中排名相同的放在一起(放在一個桶里),那么對于每個不同的桶中的元素,他們之間的大小關(guān)系就已經(jīng)確定了,對于同一個桶中的元素,s[2k][i]的前k位是一樣的,可能不一樣只有后k位,而這個我們是已經(jīng)得到了的,所以通過sa[k][i]可以算出sa[2k][i-k],桶排把排序過程復雜度降成了O(n),總體構(gòu)造的復雜度就成了O(nlogn)。DC3算法貌似可以把復雜度降到O(n)...暫時只有膜拜的份了。

            現(xiàn)在定義sa[i]為所有后綴排好序后的第i個后綴在原序列中的位置。
            定義rank[i]為后綴s[i]在后綴排好序的序列中的排名。
            當sa數(shù)組求出來了過后,就可以構(gòu)造h和height數(shù)組了。
            定義height數(shù)組為排好序的后綴中相鄰兩項的LCP(最常公共前綴),即height[i] = LCP(sa[i],sa[i-1])。
            定義h數(shù)組為原序列中的某個后綴與排好序的后綴中它的前一個的LCP,即h[i] = LCP(i,sa[rank[i]-1])。

            然后有一個hyf和yjw神牛都不知道怎么來的很牛X的定理:h[i]>=h[i-1]-1。。。所以就可以在O(n)時間內(nèi)直接for出這個h數(shù)組來。。。(這步是最詭異也最精髓的,因為沒有這個數(shù)組后綴數(shù)組就沒什么用了。。求神牛們講解下這個定理的證明。。)
            求出了h數(shù)組后height數(shù)組也可以直接得到。

            實現(xiàn)方式是用了兩個指針輪番上陣,看起來可能會有點糾結(jié)。。

            應用:
            有了h和height數(shù)組后,我們就可以用它來做很多事情。但我還不是很熟,只會求一個字符串里面可以相交的最長重復字串的長度。。
            cii(uva?)3901 Editor就是這樣一道題。
            比如abcabcabc的最長重復字串就是abcabc。
            其實求出了h和height數(shù)組后就變得很簡單,就是h或height數(shù)組中最大的一個。

            歡迎大牛神牛們前來補充和指正!

             1 /*
             2  * $Date: Fri Nov 27 09:00:37 2009 CST
             3  * $File: 3901.cpp
             4  */
             5 #include <iostream>
             6 #include <cstdio>
             7 #include <cstdlib>
             8 #include <cstring>
             9 #include <algorithm>
            10 #define MAXLEN 50000
            11 
            12 using namespace std;
            13 
            14 char s[MAXLEN+1];
            15 bool cmp(const int &a,const int &b){
            16     return s[a]<s[b];
            17 }
            18 
            19 int sa[MAXLEN+1],rank[MAXLEN+1],tmp1[MAXLEN+1],tmp2[MAXLEN+1];
            20 int h[MAXLEN+1],height[MAXLEN+1];
            21 
            22 void Solve(){
            23     scanf("%s",s);
            24     int n = strlen(s);
            25     s[n++= 0;
            26     for (int i = 0; i<n; i++)
            27         sa[i] = i;
            28     sort(sa,sa+n,cmp);
            29     
            30     rank[sa[0]] = 0;
            31     for (int i = 1; i<n; i++)
            32         if (s[sa[i]]==s[sa[i-1]])
            33             rank[sa[i]] = rank[sa[i-1]];
            34         else
            35             rank[sa[i]] = rank[sa[i-1]]+1;
            36 
            37     int *s1 = sa,*s2 = tmp1,*= tmp2, *= rank;
            38     for (int i = 1; i<n&&r[sa[n-1]]<n-1; i<<=1){
            39         //b is the barrel
            40         for (int j = 0; j<n; j++)
            41             b[r[s1[j]]] = j;
            42         for (int j = n-1; j>=0; j--)
            43             if (s1[j]>=i)
            44                 s2[b[r[s1[j]-i]]--= s1[j]-i;
            45         for (int j = n-i; j<n; j++)
            46             s2[b[r[j]]] = j;
            47         swap(s1,s2);
            48         b[s1[0]] = 0;//cause the barrel is now useless, use b as the new rank array
            49         for (int j = 1; j<n; j++)
            50             if (r[s1[j]]!=r[s1[j-1]]||r[s1[j]+i]!=r[s1[j-1]+i])
            51                 b[s1[j]] = b[s1[j-1]]+1;
            52             else
            53                 b[s1[j]] = b[s1[j-1]];
            54         swap(b,r);
            55     }
            56     //calc 
            57     for (int i = 0; i<n; i++){
            58         if (r[i] == 0)
            59             h[i] = 0;
            60         else if (i == 0||h[i-1== 0)
            61             for (h[i] = 0; s[i+h[i]]==s[s1[r[i]-1]+h[i]];h[i]++);
            62         else 
            63             for (h[i]=h[i-1]-1 ; s[i+h[i]]==s[s1[r[i]-1]+h[i]];h[i]++);
            64     }
            65     int Ans = 1;
            66     for (int i = 0; i<n; i++)
            67         Ans = max(Ans,h[i]);
            68     printf("%d\n",Ans);
            69 }
            70 int main(){
            71     int t;
            72     scanf("%d",&t);
            73     while (t--)
            74         Solve();
            75     return 0;
            76 }
            77 

            posted on 2009-11-27 09:06 TimTopCoder 閱讀(1548) 評論(0)  編輯 收藏 引用
             
            Copyright © TimTopCoder Powered by: 博客園 模板提供:滬江博客
            久久精品国产只有精品66| 国产免费久久精品99re丫y| 99久久99这里只有免费费精品| 久久久精品人妻一区二区三区四| 久久精品国产精品亚洲毛片| 国产精品免费看久久久香蕉| 亚洲国产综合久久天堂| 久久婷婷五月综合97色| 精品久久久久久无码人妻蜜桃| 久久久久波多野结衣高潮| 久久精品这里热有精品| 久久成人精品| 狠狠色噜噜狠狠狠狠狠色综合久久| 欧美国产精品久久高清| 久久人人妻人人爽人人爽| 久久久久国产一级毛片高清板| 无码人妻精品一区二区三区久久久 | 久久国产免费观看精品| 日本久久久久久久久久| 精品久久8x国产免费观看| 中文国产成人精品久久亚洲精品AⅤ无码精品 | 日韩精品国产自在久久现线拍| 伊人久久大香线蕉综合网站| 99久久夜色精品国产网站| 亚洲精品无码久久久影院相关影片| 精品久久久久久无码国产| 国产精品一久久香蕉产线看| 久久亚洲国产精品成人AV秋霞| 久久精品国产亚洲AV不卡| 精品久久久久久亚洲精品| 99久久精品免费看国产一区二区三区| 国产精品无码久久四虎| 91亚洲国产成人久久精品| 69国产成人综合久久精品| 日本强好片久久久久久AAA| 亚洲欧美日韩久久精品第一区 | 国色天香久久久久久久小说| 污污内射久久一区二区欧美日韩 | 97久久超碰国产精品旧版| 老男人久久青草av高清| 伊人久久大香线焦AV综合影院|