字典 trie 樹 從入門到入土

2022-04-28 18:12:15 字數 2995 閱讀 2468

今天再來認識乙個強大的資料結構。

字典樹又稱單詞查詢樹,trie樹,是一種樹形結構,是一種雜湊樹的變種。典型應用是用於統計,排序和儲存大量的字串(但不僅限於字串),所以經常被搜尋引擎系統用於文字詞頻統計。它的優點是:利用字串的公共字首來減少查詢時間,最大限度地減少無謂的字串比較,查詢效率比雜湊樹高。

就像這麼一棵樹,0號點為根節點,這裡的節點編號沒有多大意義。

看到這棵樹首先要注意到這可樹上儲存的元素(也就是字母)都是儲存在樹的邊上,而不是節點上,節點只是為了讓父親節點知道自己的兒子節點是多少號,便於向下深入。

定義乙個二維陣列tree[i][j],表示第i個節點與tree[i][j]之間的邊儲存著j (好難解釋啊qwq),舉個例子就好明白了:

看上圖,tree[1]['b']=2,tree[2]['f']=4.

trie樹中每個節點的左右孩子編號沒有特殊限制。

開始初始節點是root=0;tot表示用了多少個節點。

當我們插入一串字元,例如:yyfissb.

首先我們知道tree[root]['y']值為0,也就是沒有連邊,現在我們用乙個節點,tot++,tree[root]['y']=tot=1;

插入以後,這是乙個連續的單詞,我們就不能再從根節點向外連邊了,現在root = tree[root]['y'] = 1.

那麼再插入下個y值,確認tree[root(1)]['y']值為0,tot++,再次連邊tree[root]['y']=tot,root=tree[root]['y']。

直到插入完b為止。

注意:root不能直接等於tot,因為可能已經存在連邊,tot值不會改變。

void insert()//

插入單詞s

}

1.查詢單詞字元字首

和插入的寫法差不多。

插入時我們乙個乙個的按單詞順序在樹中不斷找邊,若有連邊直接線下==向下找,沒有連邊就建邊。

同樣查詢時,有連邊是不斷向下深入,而發現沒有連邊了,那麼表明這個單詞字首沒有出現過。

拿查詢字串dfzk來說:

開始root=0, tree[root]['d']=7 ,root=tree[root]['d'].

root=7, tree[root]['f']=8,root=tree[root]['f'].

root=8,tree[root]['z']=9,root=tree[root]['z'].

root=9,tree[root]['z']=0,未查找到,表明不存在字首為『dfzk』的字串。

bool

find()

return

true;//

找到了}

2.查詢單詞是否出現過以。

我們可以再定義乙個bool型陣列,在每個新單詞插入時,最後在結尾節點處進行標記,表明有單詞在此處結尾,查詢時當這一串字元不能查詢到最後一定不存在,查詢到最後是判斷節點處是否有標記。

3.查詢單詞或字首出現的次數

若要查詢單詞出現的次數,上邊的bool型可以直接改為int,結尾處每次++。

查詢字首出現的次數,路徑上所有經過的節點每次都++。

int

search()

//root經過此迴圈後變成字首最後乙個字母所在位置的後乙個位置

return sum[root];//

因為字首後移了乙個儲存,所以此時的sum[root]就是要求的字首出現的次數

}

/*

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++)

return0;

}

#include#include

#include

#include

using

namespace

std;

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

];bool

p;int

n,m;

char s[11

];void

insert()

}int

search()

//root經過此迴圈後變成字首最後乙個字母所在位置的後乙個位置

return sum[root];//

因為字首後移了乙個儲存,所以此時的sum[root]就是要求的字首出現的次數

}int

main()

scanf("%d

",&m);

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

}

Linux從入門到入土

在此開個專題,用來記錄一下在使用linux中常用的命令。持續更新 常見錯誤 dpkg i 檔名cmake dcmake install prefix usr include ar 解包 tar zxvf filename.tar 打包 tar czvf filename.tar dirname gz...

cmake 從入門到入土

你或許聽過好幾種 make 工具,例如 這些 make 工具遵循著不同的規範和標準,所執行的 makefile 格式也千差萬別。這樣就帶來了乙個嚴峻的問題 如果軟體想跨平台,必須要保證能夠在不同平台編譯。而如果使用上面的 make 工具,就得為每一種標準寫一次 makefile 這將是一件讓人抓狂的...

FFT 從入門到入土

fft 是一種可以在 o n log n 的時間複雜度內求解兩個多項式的乘積。實際上,fft 只是在求解方法上優化了 dft 離散傅利葉變換 的過程,並沒有提出新的理論。但是其高效的複雜度使得它被廣泛使用。就是使用乙個多項式的係數序列來表達這個多項式。f x sum a ix i leftright...