[LeetCode] 648. Replace Words

题目描述

In English, we have a concept called root, which can be followed by some other words to form another longer word - let’s call this word successor. For example, the root an, followed by other, which can form another word another.

Now, given a dictionary consisting of many roots and a sentence. You need to replace all the successor in the sentence with the root forming it. If a successor has many roots can form it, replace it with the root with the shortest length.

You need to output the sentence after the replacement.

Example 1:

Input: dict = [“cat”, “bat”, “rat”]
sentence = “the cattle was rattled by the battery”
Output: “the cat was rat by the bat”

Note:
The input will only have lower-case letters.
1 <= dict words number <= 1000
1 <= sentence words number <= 1000
1 <= root length <= 100
1 <= sentence words length <= 1000

解决此题的关键是实现一个字典树。

C++ 实现

class Solution {
public:
    string replaceWords(vector<string>& dict, string sentence) {
        Trie trie;
        trie.Init(dict);

        stringstream res_stream;
        // 利用stringstream 实现split 的效果
        stringstream ss(sentence);
        string word;

        while(getline(ss, word, ' '))
        {
            res_stream << trie.PrefixLookup(word);
            res_stream << " ";
        }

        string res = res_stream.str();
        res.pop_back();
        return res;
    }

private:

    class Trie
    {
        struct TrieNode
        {
            TrieNode(){}

            TrieNode(const char val, const bool is_end)
              : val(val), is_end(is_end), childrens(26, nullptr)
            {
            }

            char val;
            bool is_end;
            std::vector<TrieNode*> childrens;
        };

      public:
        Trie()
        {
            root = new TrieNode('0', false);
        }

        ~Trie()
        {
            ReleaseTrie(root);
        }

        Trie(const Trie&) = delete;
        Trie& operator = (const Trie&) = delete;
        // 初始化字典树
        void Init(const std::vector<std::string>& dict)
        {
            for (const std::string& word : dict)
            {
                Insert(word);
            }
        }
        // 找到字典树中和word有相同前缀的最短的那个,
        // 如果没有则直接返回word
        std::string PrefixLookup(const std::string& word) const
        {
            TrieNode* cur = root;
            std::string res = "";
            for (const char c : word)
            {
                res += c;
                if (cur->childrens[c - 'a'])
                {
                    if (cur->childrens[c - 'a']->is_end)
                    {
                        return res;
                    }
                    cur = cur->childrens[c - 'a'];
                }
                else
                {
                    return word;
                }
            }
            return word;
        }
      private:
        // 在字典树中插入一个word
        void Insert(const std::string& word)
        {
            if (word.empty())
                return;

            TrieNode* cur = root;
            for (const char c : word)
            {
                if (!cur->childrens[c - 'a'])
                {
                    cur->childrens[c - 'a'] = new TrieNode(c, false);
                }
                cur = cur->childrens[c - 'a'];
            }
            cur->is_end = true;
        }
        // 递归释放内存
        void ReleaseTrie(const TrieNode* root)
        {
            if (!root) return;
            bool no_children = true;
            const std::vector<TrieNode*>& childrens = root->childrens;
            for (const TrieNode* children : childrens)
            {
                if (children)
                {
                    no_children = false;
                    ReleaseTrie(children);
                }
            }

            if (no_children)
            {
                delete root;
            }
        }

        TrieNode* root;
    };
};

猜你喜欢

转载自blog.csdn.net/carbon06/article/details/81121372