C++实现LeetCode(648.替换单词)

 更新时间:2021年08月09日 15:20:18   作者:Grandyang  
这篇文章主要介绍了C++实现LeetCode(648.替换单词),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下

[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:

  1. The input will only have lower-case letters.
  2. 1 <= dict words number <= 1000
  3. 1 <= sentence words number <= 1000
  4. 1 <= root length <= 100
  5. 1 <= sentence words length <= 1000

这道题给了我们一个前缀字典,又给了一个句子,让我们将句子中较长的单词换成其前缀(如果在前缀字典中存在的话)。我们对于句子中的一个长单词如何找前缀呢,是不是可以根据第一个字母来快速定位呢,比如cattle这个单词的首字母是c,那么我们在前缀字典中找所有开头是c的前缀,为了方便查找,我们将首字母相同的前缀都放到同一个数组中,总共需要26个数组,所以我们可以定义一个二维数组来装这些前缀。还有,我们希望短前缀在长前缀的前面,因为题目中要求用最短的前缀来替换单词,所以我们可以先按单词的长度来给所有的前缀排序,然后再依次加入对应的数组中,这样就可以保证短的前缀在前面。

下面我们就要来遍历句子中的每一个单词了,由于C++中没有split函数,所以我们就采用字符串流来提取每一个单词,对于遍历到的单词,我们根据其首字母查找对应数组中所有以该首字母开始的前缀,然后直接用substr函数来提取单词中和前缀长度相同的子字符串来跟前缀比较,如果二者相等,说明可以用前缀来替换单词,然后break掉for循环。别忘了单词之前还要加上空格,参见代码如下:

解法一:

class Solution {
public:
    string replaceWords(vector<string>& dict, string sentence) {
        string res = "", t = "";
        vector<vector<string>> v(26);
        istringstream is(sentence);
        sort(dict.begin(), dict.end(), [](string &a, string &b) {return a.size() < b.size();});
        for (string word : dict) {
            v[word[0] - 'a'].push_back(word);
        }
        while (is >> t) {
            for (string word : v[t[0] - 'a']) {
                if (t.substr(0, word.size()) == word) {
                    t = word;
                    break;
                }
            }
            res += t + " ";
        }
        res.pop_back();
        return res;
    }
};

你以为想出了上面的解法,这道题就算做完了?? Naive! ! ! 这道题最好的解法其实是用前缀树(Trie / Prefix Tree)来做,关于前缀树使用之前有一道很好的入门题Implement Trie (Prefix Tree)。了解了前缀树的原理机制,那么我们就可以发现这道题其实很适合前缀树的特点。我们要做的就是把所有的前缀都放到前缀树里面,而且在前缀的最后一个结点的地方将标示isWord设为true,表示从根节点到当前结点是一个前缀,然后我们在遍历单词中的每一个字母,我们都在前缀树查找,如果当前字母对应的结点的表示isWord是true,我们就返回这个前缀,如果当前字母对应的结点在前缀树中不存在,我们就返回原单词,这样就能完美的解决问题了。所以啊,以后遇到了有关前缀或者类似的问题,一定不要忘了前缀树这个神器哟~

解法二:

class Solution {
public:
    class TrieNode {
    public:
        bool isWord;
        TrieNode *child[26];
        TrieNode(): isWord(false) {
            for (auto &a : child) a = NULL;
        }
    };
    
    string replaceWords(vector<string>& dict, string sentence) {
        string res = "", t = "";
        istringstream is(sentence);
        TrieNode *root = new TrieNode();
        for (string word : dict) {
            insert(root, word);
        }
        while (is >> t) {
            if (!res.empty()) res += " ";
            res += findPrefix(root, t);
        }
        return res;
    }
    
    void insert(TrieNode* node, string word) {
        for (char c : word) {
            if (!node->child[c - 'a']) node->child[c - 'a'] = new TrieNode();
            node = node->child[c - 'a'];
        }
        node->isWord = true;
    }
    
    string findPrefix(TrieNode* node, string word) {
        string cur = "";
        for (char c : word) {
            if (!node->child[c - 'a']) break;
            cur.push_back(c);
            node = node->child[c - 'a'];
            if (node->isWord) return cur;
        }
        return word;
    }
};

类似题目:

Implement Trie (Prefix Tree)

参考资料:

https://discuss.leetcode.com/topic/97203/trie-tree-concise-java-solution-easy-to-understand

到此这篇关于C++实现LeetCode(648.替换单词)的文章就介绍到这了,更多相关C++实现替换单词内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • OpenCV透视变换应用之书本视图矫正+广告屏幕切换

    OpenCV透视变换应用之书本视图矫正+广告屏幕切换

    透视变换是指利用透视中心、像点、目标点三点共线的条件,按透视旋转定律使承影面绕迹线旋转某一角度,破坏原有的投影光线束,仍能保持承影面上投影几何图形不变的变换。本文将为大家介绍两个OpenCV透视变换应用,需要的可以参考一下
    2022-08-08
  • 详解C/C++中低耦合代码的设计实现

    详解C/C++中低耦合代码的设计实现

    这篇文章主要为大家详细介绍了C/C++ 相关低耦合代码的设计实现,文中的示例代码讲解详细,对我们学习C++有一定的帮助,感兴趣的小伙伴可以了解一下
    2023-01-01
  • c++连续输入未知个数的数字操作

    c++连续输入未知个数的数字操作

    这篇文章主要介绍了c++连续输入未知个数的数字操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • 深入解析最长公共子串

    深入解析最长公共子串

    本篇文章是对最长公共子串进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • C 标准I/O库的粗略实现教程

    C 标准I/O库的粗略实现教程

    下面小编就为大家分享一篇C 标准I/O库的粗略实现教程,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-12-12
  • C语言实现实验设备管理系统

    C语言实现实验设备管理系统

    这篇文章主要为大家详细介绍了C语言实现实验设备管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • C++实现选择性排序(SelectionSort)

    C++实现选择性排序(SelectionSort)

    这篇文章主要为大家详细介绍了C++实现选择性排序,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-04-04
  • 基于稀疏图上的Johnson算法的详解

    基于稀疏图上的Johnson算法的详解

    本篇文章介绍了,稀疏图上的Johnson算法的详解。需要的朋友参考下
    2013-05-05
  • 如何利用OpenGL画坐标轴指示图

    如何利用OpenGL画坐标轴指示图

    C++用opengl绘制出的二维坐标,简单明了,很容易理解,下面这篇文章主要给大家介绍了关于如何利用OpenGL画坐标轴指示图的相关资料,需要的朋友可以参考下
    2022-01-01
  • 详解C语言在STM32中的内存分配问题

    详解C语言在STM32中的内存分配问题

    这篇文章主要介绍了C语言在STM32中的内存分配,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-12-12

最新评论