648. Replace Words**

648. Replace Words**

https://leetcode.com/problems/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++ 实现 1

思路: 这道题要使用 Trie 树才能获得 O(n) 的结果. 这里先使用哈希表求解.

使用 unordered_map, 不仅存储 root, 还把 root 的大小给存储. 这样方便后面访问 substr.

那么对于 record 中的每个 root, 判断 sentence 中的每个 word 的同样长度的 substr 是否刚好等于 root, 如果是的话, 那么就替换 word 为 root.

class Solution {
public:
    string replaceWords(vector<string>& dict, string sentence) {
        unordered_map<string, int> record;
        for (auto &word : dict)
            record[word] = word.size();

        stringstream ss(sentence);
        string str;
        string res = "";
        while (ss >> str) {
            int n = str.size();
            string rep = str;
            for (auto &iter : record) {
                if (iter.second <= n &&
                    iter.first == str.substr(0, iter.second) &&
                    iter.first.size() < rep.size()) { // 第三个判断保证 prefix 长度最小.
                    rep = iter.first;
                }
            }
            res += " " + rep;
        }
        
        int sz = res.size();
        return res.substr(1, sz - 1);
    }
};

C++ 实现 2

leetcode 的解法: https://leetcode.com/articles/replace-words/. 在哈希表中存储所有的 root, 当访问 sentence 中每一个 word 时, 判断 word 的 prefix 是否存在, 如果存在的话, 就用这个 prefix 来替换 word.

class Solution {
public:
    string replaceWords(vector<string>& dict, string sentence) {
        unordered_set<string> record(dict.begin(), dict.end());

        stringstream ss(sentence);
        string word;
        string res = "";
        while (ss >> word) {
            string prefix = "";
          	// 访问 word 中每一个字符, 判断 prefix 是否已经在 record 中,
          	// 这样可以保证即使 prefix 有多个, 但能得到最小的 prefix.
            for (int i = 1; i <= word.size(); ++i) {
                prefix = word.substr(0, i);
                if (record.count(prefix))
                    break;
            }
          	// 在每个单词后面添加空格.
            if (res.size() > 0) res += " ";
            res += prefix;
        }
        return res;
    }
};

C++ 实现 3

使用 Trie 树来解决. 参考两个:

class Solution {
    public String replaceWords(List<String> roots, String sentence) {
        TrieNode trie = new TrieNode();
        for (String root: roots) {
            TrieNode cur = trie;
            for (char letter: root.toCharArray()) {
                if (cur.children[letter - 'a'] == null)
                    cur.children[letter - 'a'] = new TrieNode();
                cur = cur.children[letter - 'a'];
            }
            cur.word = root;
        }

        StringBuilder ans = new StringBuilder();

        for (String word: sentence.split("\\s+")) {
            if (ans.length() > 0)
                ans.append(" ");

            TrieNode cur = trie;
            for (char letter: word.toCharArray()) {
                if (cur.children[letter - 'a'] == null || cur.word != null)
                    break;
                cur = cur.children[letter - 'a'];
            }
            ans.append(cur.word != null ? cur.word : word);
        }
        return ans.toString();
    }
}

class TrieNode {
    TrieNode[] children;
    String word;
    TrieNode() {
        children = new TrieNode[26];
    }
}

再来看 C++ 的版本:

C++ trietree solution easy to read and understand

The idea is very simple. Use the vector of string to build a trie tree. When there is a shorter root word then we stop build. For sentence, we check the tree and find is there any word to replace. For node, we record its corresponding string.

class Solution {
public:
    string replaceWords(vector<string>& dict, string sentence) {
        stringstream sen(sentence);
        string res="";
        string token;
        TrieTree tree;
        tree.buildTree(dict);
         while(getline(sen,token,' ')){
             res+=tree.replace(token);
             res+=" ";
         }
        return res.substr(0,res.size()-1);  //ignore last space
    }
    
class TrieNode{
public:
    bool end;
    string str;
    TrieNode* children[26];
    TrieNode(bool flag, string s){
        end=flag;
        str=s;
        memset(children, 0, sizeof(children));;
        }
    };
class TrieTree{
public:
        TrieNode* root;
        TrieTree(){
            root= new TrieNode(false,"");
        }
    
       void buildTree(vector<string>& dict){
            for(string s:dict){
                TrieNode* cur =root;
                for(char c:s){
                    if(cur->children[c-'a'] == NULL){
                        cur->children[c-'a'] = new TrieNode(false,"");
                        cur = cur->children[c-'a'];
                    }
                    else if(cur->children[c-'a']->end==true){   //if a shorter root exists, we just stop build
                        cur=NULL;
                        break;
                    }
                    else cur=cur->children[c-'a'];
                }
                if(cur!=NULL){    //mark the string and flag
                    cur->end=true;
                    cur->str=s;
                }
            }
           return ;
        }
        string replace(string s){
            TrieNode* cur =root;
            string res="";
            for(char c:s){
                cur=cur->children[c-'a'];
                if(cur==NULL) break;
                if(cur->end==true){
                    res=cur->str;
                    break;
                }
            }
            if(res!="") return res;
            return s;
        }
    };

};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值