一、字典樹概念:
又稱單詞查詢樹,
trie樹
,是一種
樹形結構
,是一種雜湊樹的變種。典型應用是用於統計,排序和儲存大量的
字串(但不僅限於字串),所以經常被搜尋引擎系統用於文字詞頻統計。它的優點是:利用字串的公共字首來減少查詢時間,最大限度地減少無謂的字串比較,查詢效率比雜湊樹高,但是我們時間空間這兩個東西可以相互優化的,什麼意思呢,也就是說,你時間複雜度降低了,但是你卻增加了記憶體消耗,也就是所說的空間換時間。
二、字典樹的優缺點
優點
trie樹中不同的關鍵字不會產生衝突。
trie樹中只有在允許乙個關鍵字關聯多個值的情況下才有類似hash碰撞發生。
trie樹不用求hash值,對短字串有更快的速度。通常,求hash值也是需要遍歷字串的(與hash函式相關)。
trie樹可以對關鍵字 按照字典序排序 (先序遍歷)。
每一顆trie樹都可以被看做乙個簡單版的確定有限狀態的自動機(dfa,deterministic finite automation),也就是說,對於乙個任意給定屬於該自動機的狀態(①)和乙個屬於該自動機字母表的字元(②),都可以根據給定的轉移函式(③)轉到下乙個狀態。其中:
核心思想是:空間換時間,利用字串的公共字首來減少無謂的字串比較以達到提高查詢效率的目的。
缺點空間消耗大。
給你一些單詞inn、int、ate、age、adv、ant,現在你來建立一顆字典樹。
二、建立字典樹步驟:
1.定義指向根節點的指標p(建樹過程實際上就是建立根節點)
2.從字串開始下標到結束(0-len)我們依次將字元做出節點。方法是:將字母s[i]由字典序化為數字id,當指標p指向的下乙個next[id]為空時,將其單詞計數初始化為0,從0-maxn初始化p指向的所有節點為null(一棵字典樹很明顯有很多棵子樹),同時修改指標p指向next[id],如果要統計字首,將計數節點++即可,如果統計單詞,則是這個單詞用來建完樹之後計數節點再++,大概就是這樣了,具體我們見**。
下面我們以hdu1521(統計字首)為例
傳送門
:指標**:(c++提交可以通過,g++mle,聽大佬們說是g++在申請指標記憶體的同時也會申請乙個指標對應型別大小的記憶體,這樣消耗記憶體可能就是原來的兩倍了)
#include
#include
using namespace
std;const
int maxn
= 26
;struct
trie
~ trie
(){}//析構函式};
trie root
;//根節點
void
insert
( string s)
p=p->
next
[ id
];修改指標p指向當前字元 p
->
cnt++;//統計字首
}//p
->
cnt++;統計單詞
}int
search
( string s
)return
p->
cnt;//返回統計單詞/字首的數量
}int
main
()while
( gets( s
))return 0;
}陣列**:
#includeusing namespace
std;
const
intmaxn
=1e6+5
;int
trie
[maxn
][26
];//字元位置
intnum
[maxn
];//計數
intpos=1
;void
insert
(string s
) //num[p]++;單詞數量++
}int
search
(string s
)return
num[p];
}int
main
()while
(gets(s
))printf
("%d\n"
,search(s
));return0;
} 很明顯陣列模擬是優於指標寫法的
優點trie樹中不同的關鍵字不會產生衝突。
trie樹中只有在允許乙個關鍵字關聯多個值的情況下才有類似hash碰撞發生。
trie樹不用求hash值,對短字串有更快的速度。通常,求hash值也是需要遍歷字串的(與hash函式相關)。
trie樹可以對關鍵字 按照字典序排序 (先序遍歷)。
每一顆trie樹都可以被看做乙個簡單版的確定有限狀態的自動機(dfa,deterministic finite automation),也就是說,對於乙個任意給定屬於該自動機的狀態(①)和乙個屬於該自動機字母表的字元(②),都可以根據給定的轉移函式(③)轉到下乙個狀態。其中:
核心思想是:空間換時間,利用字串的公共字首來減少無謂的字串比較以達到提高查詢效率的目的。
缺點空間消耗大。
檢索、查詢功能是trie樹最原始功能,思路就是從根節點開始乙個乙個字元進行比較。
詞頻統計
trie樹常被搜尋引擎用於文字詞頻統計。
思路:為了實現詞頻統計,我們修改了節點結構,用乙個整型變數count
來計數。對每乙個關鍵字執行插入操作,若已存在,計數加1,若不存在,插入後count
置 1。
(1. 2. 都可以用hash table做)
字串排序
trie樹可以對大量字串按字典序進行排序,思路也很簡單:遍歷一次所有關鍵字,將它們全部插入trie樹,樹的每個結點的所有兒子很顯然地按照字母表排序,然後先序遍歷輸出trie樹中所有關鍵字即可。
字首匹配
例如:找出乙個字串集合中所有以ab開頭的字串。我們只需要用所有字串構造乙個trie樹,然後輸出以a->b->開頭的路徑上的關鍵字即可。 trie樹字首匹配常用於搜尋提示。如當輸入乙個**,可以自動搜尋出可能的選擇。當沒有完全匹配的搜尋結果,可以返回字首最相似的可能。
作為輔助結構
如字尾樹,ac自動機
有窮自動機 參考資料:
與雜湊表相比
優點:
與二叉搜尋樹相比
二叉搜尋樹,又稱二叉排序樹,它滿足:
其實二叉搜尋樹的優勢已經在與查詢、插入的時間複雜度上了,通常只有o(log n),很多集合都是通過它來實現的。在進行插入的時候,實質上是給樹新增新的葉子節點,避免了節點移動,搜尋、插入和刪除的複雜度等於樹的高度,屬於o(log n),最壞情況下整棵樹所有的節點都只有乙個子節點,完全變成乙個線性表,複雜度是o(n)。
trie樹在最壞情況下查詢要快過二叉搜尋樹,如果搜尋字串長度用m來表示的話,它只有o(m),通常情況(樹的節點個數要遠大於搜尋字串的長度)下要遠小於o(n)。
字典樹 陣列模板
下面我們以hdu1521 統計字首 為例 傳送門 指標 c 提交可以通過,g mle,聽大佬們說是g 在申請指標記憶體的同時也會申請乙個指標對應型別大小的記憶體,這樣消耗記憶體可能就是原來的兩倍了 includeusing namespace std const int maxn 1e6 5 int...
字典樹模板
字典樹,又稱單詞查詢樹,trie樹,是一種樹形結構,典型應用是用於統計,排序和儲存大量的字串,所以經常被搜尋引擎系統用於文字詞頻統計。它的優點是 利用字串的公共字首來節約儲存空間,最大限度的減少無謂的字串比較,查詢效率比雜湊表高。字典樹的應用 字串的快速檢索 雜湊最長公共字首 include usi...
字典樹模板
package template public class triemod trie root new trie for string s str if find root,asdf else public static void insert final trie root,string str ...