學習 字串 Trie樹

2022-05-08 05:12:12 字數 3588 閱讀 6572

trie樹,也叫字典樹或者字首樹,是一類用空間換時間的資料結構,字典樹同時也是ac自動機的重要前置演算法,本身就可以降低字串排序的複雜度。一般來說trie樹的題目,字串的數量很多,但是每一條字串很短,且字串包含的字元屬於給定的乙個範圍類(比如全為小寫字母)
先來看看一條字串的trie樹,對於字串 "acdabd" ,它的trie樹僅僅為一條單鏈,如圖所示

綠色節點表示trie樹的根節點,藍色節點是trie樹的主要節點,橙色節點根節點的所有藍色/

橙色節點

的字元連線而成的字串表示該trie樹所表示的一條字串

假入在上圖的trie樹中再次插入一串字串 "acdbad" ,那麼原來的trie樹會變成

可以發現,兩條字串相同的字首部分合併為同一條鏈串,而不同的部分分別成為一條鏈串,這也是字典樹利用公共字首降低時間開銷的表示。

對於樹上每乙個節點,可以用乙個結構體來表示

struct

trie

};

每乙個節點都有乙個指標陣列來指向它的子節點,注意陣列的大小和題目所說明的字串內字元的種類數有關(假設所有字串只包含大寫字母)

那麼建樹的過程就是插入新字串的過程即遍歷字串每乙個字元,然後再字典樹上查詢對應的子節點,如果能找到則繼續往下進行步驟,不能找到,就建立新的子節點繼續步驟。直到把字串完全插入到樹中為止。

int insert(trie *t, const

string &str)

if(i == str.size() - 1)}}

建樹動畫:

trie樹的性質總結:

1.根節點不包含任何字元,你可以將根節點理解為空字元,表示任何一條字串的開始

2.從根節點到字串結束標誌節點(圖中為橙色節點)所走過的節點的字元連線在一起的字串,為該trie數所表示的一條字串

3.在trie數上查詢一條字串的複雜度為該字串的長度trie不適合表示很長的字串,這樣會使樹的高度變大

再探求trie樹的功能之前,先來講一講trie的優化

在上面trie樹的節點結構體中使用了指標陣列,雖然可能不是所有的指標都指向了新的記憶體,但是指標本身就占有空間,所以需要從空間方面來優化,可以用stl內的map或者unordered_map來優化,這裡要區別一下

map內部建了一顆紅黑樹,unordered_map建立了hash表,所以

1.節空間耗時間,使用map

struct

trie

};

2.節時間耗空間,使用unordered_map

struct

trie

};

建樹(插入字串)的**為

int insert(trie *t, const

string &str)

if(i == str.size() - 1

) }

}

有些題目故意卡時間,有時候unordered_map能過而map過不了1.字串的排序將所有字串插入到trie樹中,然後中序遍歷trie樹(假設字節點中,節點的順序從『a』到『z』按順序),每次遇到結束標誌就記錄當前字串,得到的就是字串排序後的結果,更適合於重新定義了26字母大小順序後的字串排序,複雜度為o(n)

2.尋找多個字串的最長公共字首

將所有字串插入到trie樹中,只需遍歷出深度最小的字串結束標誌節點即可。相反如果遍歷出深度最深的字串結束標誌節點,則是找到了多個字串中,兩兩字串的公共字首的最長字首。

3.字串檢索

判斷某個字串是否出現過(trie樹的基本作用)

4.擴充套件:01字典樹

01字典樹則是把插入字元改為了插入二進位制字元(變成了二叉樹),建樹過程和建立普通trie數一樣,只不過01字典樹可以表示很大的整數,例如深度為19的01字典樹可以表示0~220-1的所有數。

5.多模式串匹配(ac自動機反面教材)

我們知道kmp演算法可以解決單模式串匹配的問題,那麼多模式串匹配可以利用trie樹來搞,把多模式串建立為一棵trie樹,以樹上每乙個節點為起點,然後暴力匹配文字串接下來的字元與樹上當前起點以下的字元節點的字元。當然你也可以多次kmp,但是不管怎樣都會tle,解決多模式串匹配的演算法可以用ac自動機。

有時候,有的trie題目刻意會說所有的字串長度之和小於 $n$(假設 $n = 10^6$,且字串只包含大寫字母),既然知道了字串總長度,就相當於知道了trie樹的節點數量,那麼可以直接用陣列表示整個trie樹

int tree[maxn][27

];int

cnt[maxn];

int cnts = 0;

$tree[i][j]$ 表示編號為 $i$ 的節點的第 $j$ 個子節點(字元 $'a'+j$)的編號

$cnt[i]$ 表示編號為 $i$ 的節點的字串結束標誌的數量

$cnts$ 表示當前已使用的節點的數量

那麼建樹的**為(注意 $tree$ 陣列剛開始初始化為0,且編號為0的節點為根節點),ac自動機廣泛使用了基於陣列的trie樹

void insert(const

string &str)

root =tree[root][now];

}cnt[root]++;

return

;}

字串 Trie樹(字典樹)

關於這個字串的資料結構我就不多說什麼了,不知道的可以戳這裡.trie樹在oi中應用廣泛,時間優秀,缺點就是空間占用大。下文中我們將字符集大小稱為 k,模式串長度為p trie支援o np 建樹,o p 插入,查詢,刪除。可是如果二維陣列儲存的話,就要耗費kn 的空間,基本無法承受。空間上我們可以用指...

字串 Trie字典樹

目錄 trie字典樹 例題 1.什麼是字典樹?2.字典樹的作用及性質 3.建樹 code 效果圖 4.查詢 code 5.優勢 6.回到例題 code 7.結束語 8.練習 給出n個字串,以及m個詢問。每次詢問讀入乙個字串,求該字串是多少個字串的字首 每個字串長度小於10 2,n和m小於10 5。樣...

字串統計 Trie樹

題目 維護乙個字串集合,支援兩種操作 i x 向集合中插入乙個字串x q x 詢問乙個字串在集合 現了多少次。共有n個操作,輸入的字串總長度不超過 10 5,字串僅包含小寫英文本母。輸入格式 第一行包含整數n,表示運算元。接下來n行,每行包含乙個操作指令,指令為 i x 或 q x 中的一種。輸出格...