208. 實現 Trie (前綴樹)
前綴樹的思想:
- 邊表示字符(其實邊和點都行)
- 點的含義表示是否爲單詞結尾,也可另外再賦予其他含義
圖來自於:https://leetcode-cn.com/problems/implement-trie-prefix-tree/solution/208-shi-xian-trie-qian-zhui-shu-bao-gua-insert-sea/
insert
過程- 先進行遍歷,把前面所有的公共前綴遍歷完
- 然後在後面把剩下的字符加上
- 最後
end=true
,表示這裏是一個單詞的結尾
query
過程- 先進行遍歷,把前面所有的公共前綴遍歷完
- 遍歷完公共前綴,這時候
end=true
,說明前面有這個字符串insert
- 否則,沒有
struct node{
node(){
end = false;
}
vector<pair<node*, char>> edge;
bool end;
};
class Trie {
public:
node* root;
/** Initialize your data structure here. */
Trie() {
root = new node;
}
/** Inserts a word into the trie. */
void insert(string word) {
int k = 0;
node* nod = root;
for(int i = 0; i < nod->edge.size()&&k < word.size(); i ++){
if(nod->edge[i].second == word[k]){
nod = nod->edge[i].first;
i = -1;
k ++;
}
}
while(k < word.size()){
node* a = new node;
nod->edge.push_back(make_pair(a, word[k++]));
nod = a;
}
nod->end = true;
}
/** Returns if the word is in the trie. */
bool search(string word) {
int k = 0;
node* nod = root;
for(int i = 0; i < nod->edge.size()&&k < word.size(); i ++){
if(nod->edge[i].second == word[k]){
nod = nod->edge[i].first;
i = -1;
k ++;
}
}
if(k == word.size()&&nod->end) return true;
return false;
}
/** Returns if there is any word in the trie that starts with the given prefix. */
bool startsWith(string prefix) {
int k = 0;
node* nod = root;
for(int i = 0; i < nod->edge.size()&&k < prefix.size(); i ++){
if(nod->edge[i].second == prefix[k]){
nod = nod->edge[i].first;
i = -1;
k ++;
}
}
if(k == prefix.size()) return true;
return false;
}
};
/**
* Your Trie object will be instantiated and called as such:
* Trie* obj = new Trie();
* obj->insert(word);
* bool param_2 = obj->search(word);
* bool param_3 = obj->startsWith(prefix);
*/
其他解法
細節上,還可以有很多不同的地方,比如可以直接把node
的定義直接放在Trie
中,那麼每一個節點拿出來都可以看作一個Trie
。
也可以用數組來表示每個節點的後繼,數組只用26個空間。這樣在查找是否有相應後繼的時候速度加快,不用遍歷,但是犧牲了空間。這種寫法可以參考面試題 17.17. 多次搜索