Trie樹(字典樹)

2021-08-21 13:40:53 字數 3671 閱讀 3499

原作者鏈結

trie樹(字典樹)

一、引入

字典是幹啥的?查詢字的。

字典樹自然也是起查詢作用的。查詢的是啥?單詞。

看以下幾個題:

1、給出n個單詞和m個詢問,每次詢問乙個單詞,回答這個單詞是否在單詞表中出現過。

答:簡單!map,短小精悍。

好。下乙個

2、給出n個單詞和m個詢問,每次詢問乙個字首,回答詢問是多少個單詞的字首。

答:map,把每個單詞拆開。

judge:n<=200000,tle!

這就需要一種高階資料結構——trie樹(字典樹)

二、原理

在本篇文章中,假設所有單詞都只由小寫字母構成

由此可以看出:

1、字典樹用邊表示字母

2、有相同字首的單詞公用字首節點,那我們可以的得出每個節點最多有26個子節點(在單詞只包含小寫字母的情況下)

3、整棵樹的根節點是空的。為什麼呢?便於插入和查詢,這將會在後面解釋。

4、每個單詞結束的時候用乙個特殊字元表示,圖中用的『′,那麼從根節點到任意乙個『′,那麼從根節點到任意乙個『』所經過的邊的所有字母表示乙個單詞。

三、基本操作

a、insert,插入乙個單詞

1.思路

從圖中可以直**出,從左到右掃這個單詞,如果字母在相應根節點下沒有出現過,就插入這個字母;否則沿著字典樹往下走,看單詞的下乙個字母。

這就產生乙個問題:往哪兒插?計算機不會自己選擇位置插,我們需要給它指定乙個位置,那就需要給每個字母編號。

我們設陣列trie[i][j]=k,表示編號為i的節點的第j個孩子是編號為k的節點。

什麼意思呢?

這裡有2種編號,一種是i,k表示節點的位置編號,這是相對整棵樹而言的;另一種是j,表示節點i的第j的孩子,這是相對節點i而言的。

不理解?看圖

我們就按輸入順序對其編第一種號,紅色表示編號結果。因為先輸入的cat,所以c,a,t分別是1,2,3,然後輸入的是cash,因為c,a是公共字首,所以從s開始編,s是4,以此類推。

注意這裡相同字母的編號可能不同

第二種編號,相對節點的編號,紫色表示編號結果。

因為每個節點最多有26個子節點,我們可以按他們的字典序從0——25編號,也就是他們的ascll碼-a的ascll碼。

注意這裡相同字母的編號相同

實際上每個節點的子節點都應該從0編到——25,但這樣會發現許多事根本用不到的。比如上圖的根節點應該分出26個叉。節約空間,用到哪個分哪個。

這樣編號有什麼用呢?

回到陣列trie[i][j]=k。 陣列trie[i][j]=k,表示編號為i的節點的第j個孩子是編號為k的節點。

那麼第二種編號即為j,第一種編號即為i,k

2、**

void insert()//插入單詞s

return true;//找到了

}

3、如果是查詢某個單詞的話,我們用bool變數 v[i]表示節點i是否是單詞結束的標誌。

那麼最後return的是v[root],所以在插入操作中插入完每個單詞是,要對單詞最後乙個字母的v[i]置為true,其他的都是false

4、如果是查詢字首出現的次數的話,那就在開乙個sum,表示位置i被訪問過的次數,

那麼最後return的是sum[root],插入操作中每訪問乙個節點,都要讓他的sum++

這裡字首的次數是標記在字首的最後乙個字母所在位置的後乙個位置上。

比如:字首abc出現的次數標記在c所在位置的後乙個位置上,

四、完整**

1、查詢是否出現

/*

trie tree的儲存方式:將字母儲存在邊上,邊的節點連線與它相連的字母

trie[rt][x]=tot:rt是上個節點編號,x是字母,tot是下個節點編號

*/ #include#include#include#include#define maxn 2000010

using namespace std;

int tot=1,n;

int trie[maxn][26];

//bool isw[maxn];查詢整個單詞用

void insert(char *s,int rt)

rt=trie[rt][x];//為下個字母的插入做準備

}/*isw[rt]=true;標誌該單詞末位字母的尾結點,在查詢整個單詞時用到*/

}bool find(char *s,int rt)

return true;

//查詢整個單詞時,應該return isw[rt]

}char s[22];

int main()

scanf("%d",&n);

for(int i=1;i<=n;i++)

return 0;

}陣列模擬

2、查詢字首出現次數

#include#include#include#includeusing namespace std;

int trie[400001][26],len,root,tot,sum[400001];

bool p;

int n,m;

char s[11];

void insert()

scanf("%d",&m);

for(int i=1;i<=m;i++)

}陣列模擬

#include#include#include#includeusing namespace std;

char s[11];

int n,m;

bool p;

struct node

*root;

node * build()

void insert()

}int search()

return r->count;

}int main()

scanf("%d",&m);

for(int i=1;i<=m;i++)

}指標寫法

五、模板題hud 1251 統計難題 

codevs 4189 字典 

出處:

Trie樹(字典樹)

trie樹的核心思想是用空間換時間,通過在樹中儲存字串的公共字首,來達到加速檢索的目的。例如,對於一棵儲存由英文本母組成的字串的trie樹,如下圖 trie樹在實現的時候,可以用左兒子右兄弟的表示方法,也可以在每個節點處開設乙個陣列,如上圖的方法。trie樹的主要操作是插入 查詢,也可以進行刪除。插...

字典樹 Trie樹

字典樹 trie樹 顧名思義是一種樹形結構,屬於雜湊樹的一種。應用於統計 排序 查詢單詞 統計單詞出現的頻率等。它的優點是 利用字串的公共字首來節約儲存空間,最大限度地減少無謂的字串比較,查詢效率比雜湊表高。字典樹的結構特點 根節點不代表任何字元。其他節點從當前節點回溯到根節點可以得到它代表的字串。...

字典樹 trie樹

amy 56 ann 15 emma 30 rob 27 roger 52首先存入amy,level 0表示根,不持有資料。其餘每個節點持有乙個字元 葉子節點持有資料,且持有的字元為 0 level 0 root a level 1 m level 2 y level 3 0 56 level 4新...