字典樹 (Trie)ide
用於存儲字符串。樹的每條邊剛好表示一個字符,每一個節點表明從根到該節點的路徑所對應的字符串。spa
簡介與操做實現可見藍書P82~83。3d
Trie字典樹很好地利用了前綴,節省了不少空間。code
1 //先說明一下:本代碼段的字符串d的下標都是從1開始 2 inline void insert(char *d)//向Trie樹插入字符串d 3 { 4 int l=strlen(d+1),now=0,num; 5 for(int i=1;i<=l;++i) 6 { 7 num=d[i]-'a';//字符化爲數字下標 8 if(!tree[now][num])//當前節點不存在該字母的邊,即該字母還未在當前節點插入過 9 tree[now][num]=++cnt; 10 now=tree[now][num]; 11 } 12 ed[now]=1;//最後標明一下字符串結尾節點,說明該節點表明了一個已插入過的字符串 13 } 14 15 inline int fin(char *d)從Trie樹查詢字符串d 16 { 17 int l=strlen(d+1),now=0,num; 18 for(int i=1;i<=l;++i) 19 { 20 num=d[i]; 21 if(!tree[now][num])//不存在對應節點了,說明Trie中沒有這個串 22 return 0; 23 now=tree[now][num]; 24 } 25 return ed[now];//查詢到最後還要看當前節點是否表明一個插入過Tire樹的字符串 26 }
應用:blog
一、前綴查找。字符串
在Trie樹中查找一個字符串的前綴。無論Trie樹中插入了多少個字符串,查找的複雜度都是優秀的O(n)(n爲當前字符串的長度)。event
還有一種邊插邊找前綴的方法。若是當前串插入Trie樹時沒有新建任何節點,那它就是它的末尾節點的子樹中全部串的前綴;若是當前串插入Trie樹時通過了某個串x的末尾節點,那麼x就是當前串的一個前綴。class
二、異或相關。cli
將每一個數看作二進制的01串。從Trie樹中找當前數字異或值最大的數,只要儘量向與當前邊反方向的邊走就好。bfc
1 inline int fin(int a)//從Trie樹中找與a異或的結果最大的數,並返回這個結果 2 //a爲int範圍的一個正整數 3 { 4 int ret=0,c,now=1;//這裏的Trie數根節點的編號爲1 5 for(int k=30;k>=0;--k) 6 { 7 if((a&(1<<k))^(1<<k))//看下a當前位取反的結果 8 c=1; 9 else 10 c=0; 11 if(tree[now][c])//當前點能有a當前位表明邊的另外一側方向的邊的話,就走那條邊 12 { 13 now=tree[now][c]; 14 ret|=1<<k;//維護答案(當前走的與a的當前位不同的話,答案的當前位就是1,由於是異或) 15 } 16 else//沒有的話,有哪條邊,就走那條邊嘍。 17 //Trie樹中至少有一個數的話,必定能一直走下去 18 now=tree[now][c^1]; 19 } 20 return ret; 21 }