後綴樹

概念,定義

後綴樹是一種樹型數據結構,使用後綴樹可以快速解決很多字符串相關的問題,功能非常強大。很多文章在說到後綴樹時,都會首先提及Tries樹。實際上Tries是一種簡單版本的後綴樹,後綴樹也可以說是壓縮後的Tries樹。總而言之,Tries樹和後綴樹有很多相似之處,後綴樹在時間效率和空間效率都比Tries樹要好,不過後綴樹相應的就很難理解。很多介紹後綴樹的文章都難免讓初學者陷入混亂。

字符串的後綴

比如字串S:hello,它的後綴包括:
hello, ello, llo, lo, o, $(空串)
更一般的定義:如果S=t1t2...ti...tn是一個字串, 那麼Ti=titi+1...tn是S的起始於i的後綴。例如:

T1 = hello = S

T= ello

T3 = llo

T= lo

T5 = o

T6 = $
類似的我們可以得到S的前綴:$, h, he, hel, hell, hello。注意,S的子串是一個後綴的前綴,是一個前綴的後綴。比如ell是S的一個子串,它是後綴T2的前綴,是前綴hell的後綴。

suffix Trie與suffix Tree

對於S:bananas
它的後綴Trie和後綴樹分別如下所示:
現在來理解它們的區別還比較困難。總結而言可以概括爲:後綴樹要比後綴Tries省空間,後綴Tries構造比較直接簡單,時間複雜度爲O(n2),而且空間複雜度也是O(n2)後綴樹的構造很複雜,不容易理解,不過它的時間複雜度和空間複雜度都爲O(n)。
後綴Tries沒有家喻戶曉的原因正是因爲它的平方級開銷,這使得它在最需要它的領域 -- 長串搜索中被拒之門外。
可以用下面的結構來表示Tries
class Edge {
        char ch ;    //邊代表的字符
        Node *node ; //邊指向的點   
};
class Node {
        Edge *first ; //以該節點出發的第一條邊
        Edge *next  //下一條邊
        bool isEnd  //以該節點結尾的字串是否存在
};

class Node {
        char ch ;         //該節點代表的字符
        Node *child ;    //第一個子節點
        Node *sibling  //兄弟節點
        bool isEndl ;    //以該節點結尾的字串是否存在
};

suffix link(後綴鏈接)

也叫後綴指針,它指示下一個更短的後綴。即,如果一個後綴表示文本的第0到第n個字符,那麼它的後綴指針指向的節點表示文本的第1個到第n個字符。
它的存在有什麼好處呢?有了後綴指針,我們就可以方便的從一個後綴跳到另一個後綴,這是使後綴樹的構造算法降爲O(n)的保證。

後綴樹的特性

後綴樹通過自身的特性去解決一些複雜的匹配問題。
經過證明,在最壞的情況下,後綴樹的節點數也不會超過2N。
前綴相同的後綴共享同樣的邊
後綴指針指向下一個更短的後綴

問題來源

字符串匹配是程序員經常要面對的問題。字符串匹配算法的改進可以使很多工程受益良多,比如數據壓縮和DNA排列。O(n2)的傳統匹配算法在面對長字串時無能爲力,後來出現了很多改進的算法,比如KMP,Boyer-Moore算法等使複雜度降低O(N+M),效率大大改進。在基因工程的應用中,通常都需要頻繁在基因庫中定位一個基因數據,對於一個大型的基因庫,顯然O(N+M)的算法仍然無法滿足需要。後綴Tries亮出了O(M)的底牌,徹底鄙視了其它算法的成績,後綴Tries對比的次數僅僅相當於被搜索串的長度!
但有一點不能忘了,後綴Tries的構造是需要時間和空間的,而且都是平方級。
直到1976年,Edward McCreigh發表了一篇論文,後綴樹自此問世了。後綴Tries的困境被徹底打破。
然而,McCreigh最初的構造算法是有缺陷的,原則上它要按逆序構造,也就是說字符要從末端開始插入。如此一來,便不能作爲在線算法,它變得更加難於應用與實際問題,如數據壓縮。
20年後, 來自赫爾辛基理工大學的Esko Ukkonen把原算法作了一些改動,把它變成了從左往右。

後綴樹的構造

很多介紹後綴樹的文章,都把重點放在後綴樹的構造過程上。可見,後綴樹的構建過程是該算法的關鍵。

歷史

1973年,Weiner發明了最初的O(n)算法,Knuth稱之爲1973算法。Weiner提出的方法採用自右向左處理,從最短的後綴開始,依長度遞增順序不斷把後綴添加到樹中。
1976年,McCreigh提出了空間效率更高的算法。McCreight提出的方法依長度遞減順序把後綴逐個添加到樹中。
20年後,Esko Ukkonen對其改進,提出了更簡單的在線算法。

Ukkonen構造算法

待續



應用

後綴樹天生就是用來解決長串搜索問題的,而且效率很高。因此,只要涉及在某個固定長數據序列中多次查找子序列的問題,都可以應用後綴樹。

缺點

後綴樹的構造可以用Ukkonen算法在線性時間內完成,但是不僅構造算法實現相當複雜,而且後綴樹存在着致命弱點:空間開銷大且對大字母表時間效率不理想。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章