TrieTree(字典树)

TrieTree(字典树)


定义

TrieTree,,字典树,又叫前缀树,单词查找树,是一种针对字符串前缀进行维护的数据结构,给定一个字符串集合构建的前缀树,可以在树中查找字符串或者字符串的前缀。

分析

一般情况下,字符串仅有小写字母构成,以下分析仅考虑包含小写字母的字符串,前缀树每个节点最多有26个子树,从根节点开始,向下延伸的每条路径代表一个字符(a~z),通过字典集合可以构建出整个前缀树,以[them, zip, team, the, app, that] 为例,前缀树如下图:

在前缀树中,终端叶子节点均为有效节点,针对不同问题可能保存着不同的val值。

具体实现

数据结构

class TrieTree {
private:
    struct TrieNode {
        bool val = false;
        TrieNode *child[26];
    };
    TrieNode root;
public:
    TrieTree() {
        root = new TrieNode();
    }
    void insert(string &word);
    bool search(string &word)
}

建树

void insert(string &word) {
    TrieNode *p = root;
    for(auto k : word) {
        int index = int(k - 'a');
        if(p->child[index] = nullptr) {
            p->child[index] = new TrieNode();
        }
        p = p->child[index];
    }
    p->val = true;
}

搜索

bool search(string &word) {
    TrieNode *p = root;
    for(auto k : word) {
        int index  = int(k - 'a');
        if(p->child[index] == nullptr) return false;
        p = p->child[index];
    }
    return p->val;
}

字典树相关问题

单词替换

题目描述

在英语中,我们有一个叫做 词根(root) 的概念,可以词根后面添加其他一些词组成另一个较长的单词——我们称这个词为 继承词(successor)。例如,词根an,跟随着单词 other(其他),可以形成新的单词 another(另一个)。

现在,给定一个由许多词根组成的词典 dictionary 和一个用空格分隔单词形成的句子 sentence。你需要将句子中的所有继承词用词根替换掉。如果继承词有许多可以形成它的词根,则用最短的词根替换它。

你需要输出替换之后的句子。

示例1

输入:dictionary = ["cat","bat","rat"], sentence = "the cattle was rattled by the battery"
输出:"the cat was rat by the bat"

示例2

输入:dictionary = ["a","b","c"], sentence = "aadsfasf absbs bbab cadsfafs"
输出:"a a b c"

Solution

以词根构建字典树,这题实际就是在一组单词种对每个单词查找其在字典中的最短前缀,并替换。

Code

class Solution {
private:
    struct TrieNode {
        bool val;
        TrieNode *child[26];
    };
    TrieNode *root = new TrieNode();
public:
    vector<string> split(string &str, char d) {
        vector<string> ans;
        string temp = "";
        for(auto k : str) {
            if(k == d) {
                ans.push_back(temp);
                temp = "";
                continue;
            }
            temp += k;
        }
        if(temp != "") ans.push_back(temp);
        return ans;
    }

    string replaceWords(vector<string>& dictionary, string sentence) {
        root = new TrieNode();
        for(auto k : dictionary) {
            insert(k);
        }
        vector<string> sq = split(sentence, ' ');
        string out = "";
        for(auto k : sq) {
            string prefix = shortPrefix(k);
            if(out != "") out += " ";
            if(prefix == "") out += k;
            else out += prefix;
        }
        return out;
    }

    void insert(string &prefix) {
        TrieNode *p = root;
        for(int i = 0; i < prefix.length(); ++i) {
            int k = int(prefix[i] - 'a');
            if(p->child[k] == nullptr) p->child[k] = new TrieNode();
            p = p->child[k];
        }
        p->val = true;
        return;
    }

    string shortPrefix(string &word) {
        string ans = "";
        TrieNode *p = root;
        for(int i = 0; i < word.length(); ++i) {
            int k = int(word[i] - 'a');
            if(p->child[k] == nullptr) {
                if(p->val) return ans;
                else return "";
            }
            if(p->val) return ans;
            ans += word[i];
            p = p->child[k];
        }
        if(p->val) return ans;
        return "";
    }
};
posted @ 2022-09-24 10:27  落水清心  阅读(66)  评论(0编辑  收藏  举报