Trie 字典树/前缀树

前缀树(Trie,又称字典树)是一种高效处理字符串的树形数据结构,适用于前缀匹配、自动补全、敏感词过滤等场景。


1. 核心思想

  • 节点结构:每个节点存储子节点指针(如数组或哈希表)和结束标记(isEnd)。
  • 路径共享:相同前缀的字符串共享路径,节省空间。
  • 时间复杂度:插入和查询均为O(L)(L为字符串长度)。

2. C++实现代码

基础版本(支持小写字母)

#include <vector>
#include <string>
using namespace std;

class Trie {
private:
    struct TrieNode {
        vector<TrieNode*> children;
        bool isEnd;
        TrieNode() : children(26, nullptr), isEnd(false) {}
    };
    TrieNode* root;

public:
    Trie() : root(new TrieNode()) {}

    void insert(const string& word) {
        TrieNode* node = root;
        for (char c : word) {
            int idx = c - 'a';
            if (!node->children[idx]) {
                node->children[idx] = new TrieNode();
            }
            node = node->children[idx];
        }
        node->isEnd = true;
    }

    bool search(const string& word) {
        TrieNode* node = findNode(word);
        return node && node->isEnd;
    }

    bool startsWith(const string& prefix) {
        return findNode(prefix) != nullptr;
    }

private:
    TrieNode* findNode(const string& s) {
        TrieNode* node = root;
        for (char c : s) {
            int idx = c - 'a';
            if (!node->children[idx]) return nullptr;
            node = node->children[idx];
        }
        return node;
    }
};

优化版本(支持任意字符,使用哈希表)

#include <unordered_map>
class Trie {
private:
    struct TrieNode {
        unordered_map<char, TrieNode*> children;
        bool isEnd;
        TrieNode() : isEnd(false) {}
    };
    TrieNode* root;

public:
    // 方法同上,仅需修改字符处理逻辑
    void insert(const string& word) {
        TrieNode* node = root;
        for (char c : word) {
            if (!node->children.count(c)) {
                node->children[c] = new TrieNode();
            }
            node = node->children[c];
        }
        node->isEnd = true;
    }
    // search和startsWith方法类似调整
};

3. 功能扩展

统计前缀出现次数

struct TrieNode {
    int pass; // 经过该节点的字符串数
    int end;  // 以该节点结尾的字符串数
    // ...其他成员
};

void insert(const string& word) {
    TrieNode* node = root;
    node->pass++;
    for (char c : word) {
        int idx = c - 'a';
        if (!node->children[idx]) {
            node->children[idx] = new TrieNode();
        }
        node = node->children[idx];
        node->pass++;
    }
    node->end++;
}

int countPrefix(const string& prefix) {
    TrieNode* node = findNode(prefix);
    return node ? node->pass : 0;
}

删除操作

void remove(const string& word) {
    if (!search(word)) return;
    TrieNode* node = root;
    node->pass--;
    for (char c : word) {
        int idx = c - 'a';
        if (--node->children[idx]->pass == 0) {
            delete node->children[idx];
            node->children[idx] = nullptr;
            return;
        }
        node = node->children[idx];
    }
    node->end--;
}

4. 应用场景

  • 自动补全:输入前缀时快速匹配候选词。
  • 敏感词过滤:构建敏感词Trie树,高效检测文本。
  • 词频统计:统计大量字符串的出现次数。

5. 复杂度分析

  • 空间:O(N * L)$(N为字符串数量,L为平均长度)。
  • 时间:插入、查询、删除均为O(L)。

参考实现:LeetCode 208. 实现 Trie

滚动至顶部