算法笔记——字典树

算法笔记——字典树(Trie)

字典树又称为前缀树,是一种保存字符串(不限于字符串)的树形结构,字典树充分利用了字符串的公共前缀,节省了存储空间,同时可以用于求解一些与前缀有关的问题

结构

字典树通过边来表示表示字符,每个节点所代表的字符序列就是从根节点到该节点的路径上的所有字符,同时为每个节点设置一个标志位来表示这个节点是否是单词的结尾。

以"able"、“cat”、“cater”,“can”、“to”、"two"所构成的字典树为例

实现

节点定义:
vector<TrieNode *> children:存储边
如:children[‘c’-‘a’]不为空,那么该节点就有一条表示字符c的边
isEnd:单词结束标志

struct TrieNode
{
    
    
    vector<TrieNode *> children;
    bool isEnd;
    TrieNode()
    {
    
    
        children.resize(26);
        isEnd = false;
    }
};

字典树定义:
TrieNode *root
树的根节点,插入和查找操作都从根节点开始
void insert(string word)
插入单词word
从根节点开始按照word的单词顺序向下查找
如果遇到null,就new一个新节点
如果有节点,则直接走到已存在的节点
单词结束时置节点的isEnd为true
bool search()
查找单词
从根节点开始按照word的单词顺序向下查找
如果遇到空则不存在该单词,返回false
如果查到结尾单词且节点的isEnd为true则返回true

struct Trie
{
    
    
    TrieNode *root = new TrieNode();
    
    void insert(string word)
    {
    
    
        TrieNode *node = root;
        for (char c : word)
        {
    
    
            if (!node->children[c - 'a'])
                node->children[c - 'a'] = new TrieNode();
            node = node->children[c - 'a'];
        }
        node->isEnd = true;
    }
    
    bool search(string word)
    {
    
    
        TrieNode *node = root;
        for (char c : word)
        {
    
    
            if (!node->children[c - 'a'])
                return false;
            node = node->children[c - 'a'];
        }
        return node->isEnd;
    }
};

应用

1、字典树在串的快速检索中的应用。

给出N个单词组成的熟词表,以及一篇全用小写英文书写的文章,请你按最早出现的顺序写出所有不在熟词表中的生词。在这道题中,我们可以用字典树,先把熟词建一棵树,然后读入文章进行比较,这种方法效率是比较高的。

2、字典树在“串”排序方面的应用
给定N个互不相同的仅由一个单词构成的英文名,让你将他们按字典序从小到大输出用字典树进行排序,采用数组的方式创建字典树,这棵树的每个结点的所有儿子很显然地按照其字母大小排序。对这棵树进行先序遍历即可。

3、字典树在最长公共前缀问题的应用
对所有串建立字典树,对于两个串的最长公共前缀的长度即他们所在的结点的公共祖先个数,于是,问题就转化为最近公共祖先问题。

如果Trie树的平均高度为h,则Trie树的查询复杂度为O(h),trie树的建立复杂度为O(n*h)

关于最近公共祖先问题可以先参考以下文章,等有时间再填这个坑
最近公共祖先问题
最近公共祖先问题

例题

(待填)

猜你喜欢

转载自blog.csdn.net/shn111/article/details/123941151