考虑一棵拥有 26 个子节点指针的树,用边来代表字母,而从根结点到树上某一结点的路径就代表了一个字符串。在这棵树上,还需要一个布尔型变量,表示以当前节点作为结束的串是否存在。
Trie 最基本的应用就是存储和查询字符串是否存在。
例题 1:力扣 208. 实现 Trie (前缀树)
遵循力扣风格,用类来实现,代码:
参考代码
struct Node {bool val = false;Node* next[26] = {NULL};};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 n = word.length();Node* p = root;for (int i=0; i<n; ++i) {char cur = word[i];if (p->next[cur - 'a'] != nullptr) {p = p->next[cur - 'a'];} else {p->next[cur - 'a'] = new Node();p = p->next[cur - 'a'];}}p->val = true;}/** Returns if the word is in the trie. */bool search(string word) {int n = word.length();Node* p = root;for (int i=0; i<n; ++i) {char cur = word[i];if (p->next[cur - 'a'] != nullptr) {p = p->next[cur - 'a'];} else {return false;}}return p->val;}/** Returns if there is any word in the trie that starts with the given prefix. */bool startsWith(string prefix) {int n = prefix.length();Node* p = root;for (int i=0; i<n; ++i) {char cur = prefix[i];if (p->next[cur - 'a'] != nullptr) {p = p->next[cur - 'a'];} else {return false;}}return true;}};/*** 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);*/
本数据结构的逻辑比较简单,你也可以尝试写出符合自己逻辑的版本。
例题 2:力扣 421. 数组中两个数的最大异或值
Trie 的另一个应用,和异或有关,你可能需要先行熟悉「位运算」相关知识。将数的二进制表示看做一个字符串,就可以建出字符集为 的 Trie 树。
题解请参考官方题解的字典树方法。
参考代码:
class Trie {private:const int kMaxBits = 31;Trie* next[2] = {nullptr};public:void add(int x) {Trie* p = this;for (int i = kMaxBits - 1; i >= 0; --i) {bool bit = x >> i & 1;if (p->next[bit] == nullptr) {p->next[bit] = new Trie();}p = p->next[bit];}}int match(int x) {int ans = 0;Trie* p = this;for (int i = kMaxBits - 1; i >= 0; --i) {bool bit = x >> i & 1;ans <<= 1;if (p->next[!bit] != nullptr) {++ans;p = p->next[!bit];} else {p = p->next[bit];}}return ans;}};class Solution {public:int findMaximumXOR(vector<int>& nums) {int n = nums.size();Trie t;int ans = 0;for (int i=1; i<n; ++i) {t.add(nums[i - 1]);ans = max(ans, t.match(nums[i]));}return ans;}};
拓展练习(难度较高):AcWing 3485. 最大异或和
