字串演算法 字典樹Trie入門

2022-05-04 20:36:09 字數 1814 閱讀 3890

顧名思義,字典樹(也叫字首樹)就是可以像字典那樣來儲存一些單詞的集合。

如圖所示:

(來自oiwiki)

設根節點的標號為$0$,然後其餘結點依次編號;我們用陣列來存每個節點的所有子節點

更具體地,設陣列$ch[maxnode][sigmasize]$,其中$maxnode$表示最大可能的節點個數,$sigmasize$是字元集合。$ch[i][j]$表示結點標號為$i$的結點 的 字母編號為$j$(比如說,j=字母-'a')的子節點的結點標號。如果$ch[i][j]$為$0$,則表示$i$沒有字母編號為$j$的子節點。

插入的時候,直接從根節點開始遍歷,根據要插入的字串往下面走,如果碰到沒有的字元就新插入結點就可以了。

scanf("

%s",s+1

);//

插入字串 這顆trie根節點是從1開始的

int u=1,len=strlen(s+1

);for(int j=1;j<=len;j++)

查詢與操作是相似的,這裡不再贅述。

不過要注意,在字典樹裡面可以查詢到的不一定就是單詞,還有可能是單詞的字首。

所以我們還需要再新增乙個標記陣列$tag[i]$表示節點標號為$i$的結點是否為乙個單詞的結尾,我們把這個節點叫做單詞結點。顯而易見,我們之前的那個插入就要改一下了。

同樣的,這個標記陣列還可以幹一些別的事情,比如在字串被附了權值的情況下存這個字串(以當前結點結尾的字串)的權值。

scanf("

%s",s+1

);int u=1,len=strlen(s+1

);for(int j=1;j<=len;j++)

if(tag[u]==0) ... //

不存在

其實直接把單詞結點的標記清掉就可以了。

但是呢,也可以針對特殊情況特殊處理一下。

分類討論一下:

那麼直接把整個單詞全部刪掉就可以了。(清$ch$

如果被刪除單詞的那條鏈上某處有了分支,然後那個分支應該是有一支是表示被刪除單詞的,其他的都不是,那麼刪掉這一支就可以了(清$ch$

其實還是有些麻煩,還不如直接清標記...

於是他錯誤的點名開始了

1 #include2 #include3 #include4 #include5 #include6

using

namespace

std;

7#define n 500005

8int ch[n][26];//

結點i的為j+'a'子節點的節點標號

9char s[55

];10

int n,m,tag[n],tot=1

; 11

intmain()

1226 tag[u]=1;//

標記這個結點是單詞結點

27//

--- 28}

29 scanf("

%d",&m);

30while(m--)

3140

if(tag[u]==1)41

45else

if(tag[u]==2

)46 puts("

repeat");

47else puts("

wrong");

48}49return0;

50 }

view code

做了例題之後,發現$trie$幹的事情$map$也能幹,$hash$也能幹,不就是存個單詞,查個單詞嘛!

別急,他還有很多用法...檢索字串只是最基本的操作而已...

字串 Trie字典樹

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

字串 Trie樹(字典樹)

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

Trie樹 字典樹(字串排序)

有時,我們會碰到對字串的排序,若採用一些經典的排序演算法,則時間複雜度一般為o n lgn 但若採用trie樹,則時間複雜度僅為o n trie樹又名字典樹,從字面意思即可理解,這種樹的結構像英文本典一樣,相鄰的單詞一般字首相同,之所以時間複雜度低,是因為其採用了以空間換取時間的策略。下圖為乙個針對...