字典樹,又稱字首樹,是用於快速處理字串的問題,能做到快速查詢到一些字串上的資訊。
另外,trie樹在實現高效的同時,會損耗更多的空間,所以trie是一種以空間換時間的演算法。
trie的思想十分簡單,其實我在很早之前就已經懂了trie的思想,只不過一直沒有實現,所以就……
咕咕,沒事,trie無論是思想還是**思想都還是很簡單。現在我重新再搞回trie也很快就**實現了。
trie是思想其實用圖更容易展現。下面放一張圖給大家看看,相信大家很快就會明白了。
如果我們插入字串:
上面就是一顆我們建的trie樹。
如果我們要查詢「zlh」,那麼就會沿著1->2->3點找下去。
如果我們要查詢「akioi」,那麼我們就會沿著4->5->9->10->11點找
也可以十分容易發現"ak"是"akioi"的字首。
那麼大家現在應該就能明白trie的構造了吧。
簡單說就是順著之前trie樹的構造去插入點,例如我們最後插入"aknoip",就會先走過"a"和"k",然後發現沒有匹配的字元了,就先後新建了'n','o','i','p',這幾個點。複雜度o(len(字串))。
查詢就會沿著trie的構造乙個乙個跳,所以查詢複雜度是o(len(字串))。
那麼trie的思想就是這樣了。
明白了思想,實現就應該很簡單了吧,這裡通過一道例題來實現trie。
題目:p2580 於是他錯誤的點名開始了
struct kkktrie[maxn];
void insert(string s) //清0
}trie[400001];
int n,t,num;
string s[400001];
void insert(string s)
bool ans=false;
for(int i=1;i<=n;i++) //判斷是不是字首
}if(ans==true)printf("no\n"); //輸出
else printf("yes\n");}}
題目:immediate decodability
這道題和上面那道題一模一樣,不過輸入比較噁心,而且資料範圍也比較小。
這裡的輸入就是不斷輸入字串s,然後將字串s插入到trie中,直到s='9'為止。
到了s='9',就將之前的s都像上面的一樣查詢一邊,輸出答案,然後清0。
**:
#includeusing namespace std;
struct kkk
}trie[2001];
int n,t,num,t;
string s[400001];
void insert(string s)
insert(s[n]);n++; //如果不是『9』就插入}}
題目:the xor largest pair
這道題是一道變向的trie,也是trie的乙個基本應用。
思路:1、首先將a[i]轉換為二進位制的字串存起來,記得空位要補0
2、然後將這些字串都插入到trie裡。
3、查詢每乙個字串,找到以每乙個數和另外其他數的最大異或和。
那麼問題就是怎麼找乙個數和另外其他數的最大異或和了。
我們知道,異或是不同就為1,相同就為0,所以我們因盡量讓高位的二進位制為1。
所以我們查詢的時候就倒著查,也就是如果s[i]為0,那麼我們就查1。但是沒有1怎麼辦,我們總不能就此放棄吧,於是我們繼續查0。
最後取個最大值就ok了。
看看**:
#includeusing namespace std;
struct kkk
}trie[4000001];
int n,t,num,ans;
int x[1000001];
void insert(string s)
int main()
for(int i=1;i<=n;i++)
printf("%d\n",ans);
}
題目大意:給你n個資訊和m個密碼,要你求出對於每乙個密碼都多少資訊,使這些資訊的字首和密碼的字首相同。
理解清題目,這道題就很簡單了,我們用資訊來在建立trie時多維護乙個資料sum,存的是有多少個資訊經過這個節點。那麼我們在查詢時,先統計有多少資訊是密碼的字首再加上當前節點的sum就是答案。
#includeusing namespace std;
struct kkk
}trie[400001];
int n,t,num,ans;
string s[400001];
void insert(string s)
for(int i=1;i<=m;i++)
}
題目在這裡:「一本通 2.3 例 3」nikitosh 和異或
首先對於如何求異或最大值我們已經在上文學到了,現在我們要求的是兩個沒有覆蓋的區間異或的和。
異或有乙個性質:就是據有可減性,也就是說我們記字首異或sum陣列,如果求[l,r]的異或和,那麼答案就是sum[r]^sum[l-1];字尾異或也是一樣的
所以我們可以對於每乙個位置i都求一遍以i為結尾的區間中,最大的區間異或值。方法是將i前面的每乙個字首sum陣列都插入到trie中,然後find(sum[i]),答案計為l陣列。
另外,對於每乙個位置i都求一遍以i為開頭的區間中,最大的區間異或值。方法是將i後面的每乙個字尾sum陣列都插入到trie中,然後find(sum[i]),答案計為r陣列。
那麼對於每乙個位置i,都統計前面的最大的l,記錄下來。表示的是i前面的最大區間異或和
對於每乙個位置i,都統計後面的最大的r,記錄下來。表示的是i後面的最大區間異或和
那麼答案就是對於每乙個位置i的 前面的最大區間異或和 和 後面的最大區間異或和 的 和 的最大值
**:
#includeusing namespace std;
struct kkk
}trie[8000001];
int n,t,num,ans;
int x[1000001],l[1000001],r[1000001],s[35];
void insert(int x)
for(int i=31;i>=0;i--)
}int find(int x)
trie樹學習總結(字典樹模板)
trie樹 演算法簡介 字典樹,也叫trie樹,是一種比較實用的資料結構,無論是在acm競賽的題目中,還是字串相關的某些實際應用領域內,它都能發揮巨大的作用。首先來看看字典樹的本質是什麼。它其實是一棵儲存了很多字串的樹,這棵樹上的每一條邊就是某個或某些字串中的乙個字元,而從根節點到某乙個特定節點所經...
Trie 樹學習下
今天把trie樹徹底的看了下。發現網上有兩篇非常好的文章,通過他們的部落格,我對trie樹有了大題的了解。並且通過理解 消化 綜合他們的知識,再結合我自己的程式設計愛好,我也把具體的程式實現了一遍,這樣能對trie樹有更加深刻的認識!他們是 勇幸 thinking 和 maik 感謝他們。下面的分析...
Trie樹的學習
所寫內容,是對自己所學知識的乙個記錄罷了。1.簡介 最近在做中國人名識別的時候,看到一篇文章是基於角色的人名識別,而角色字典中有2個角色是用雙陣列tire樹來建立的,當時沒有看懂,於是來先學習trie樹。trie樹,又稱字典樹,單詞查詢樹或者字首樹等,是一種快速 檢索的多叉樹結構。比如,英文本母的字...