leetcode: 758. 字符串中的加粗单词

该博客讨论了如何利用Trie数据结构有效地解决LeetCode上的758题——VIP字符串中的加粗单词。通过构建Trie树,可以高效地找到字符串中的关键词并加粗,同时确保使用最少的标签。文章详细介绍了三种不同的解决方案,包括使用数组、哈希集合以及Trie树,并提供了对应的代码实现。此外,还提到了与该题相关的其他类似题目。
摘要由CSDN通过智能技术生成

题目来源

题目描述

给定一个字典 words 和一个字符串 S,将所有 S 中出现的关键词加粗(所有在标签 <b> </b> 中的字母都会加粗。)

返回的字符串需要使用尽可能少的标签,当然标签应形成有效的组合。

例如,给定 words = [“ab”, “bc”] 和 S = “aabcd”,需要返回 “a<b>abc</b>d”。注意返回 “a<b>a<b>b</b>c</b>d” 会使用更多的标签,因此是错误的。

Example 1:

Input:
s = “abcxyz123”
dict = [“abc”,“123”]
Output:
abcxyz123

Example 2:

Input:
s = “aaabbcc”
dict = [“aaa”,“aab”,“bc”]
Output:
aaabbcc”

注:
words 长度的范围为 [0, 50]。
words[i] 长度的范围为 [1, 10]。
S 长度的范围为 [0, 500]。
所有 words[i] 和 S 中的字符都为小写字母。

class Solution {
public:
    string boldWords(vector<string>& words, string str){
        
    }
};

题目解析

思路

  • 使用一个数组bold,标记所有需要加粗的位置为true,初始化所有为false。
  • 首先判断每个单词word是否是S的子串
  • 如果是,则将子串所有的位置在bold上置true
class Solution {
public:
    string boldWords(vector<string>& words, string str){
        int n = str.size();
        std::vector<bool> bold(n, false);
        // 判断每一个word是不是str的子串
        for(auto word : words){
            int len = word.size();
            for (int i = 0; i <= n - len; ++i) {
                if(str[i] == word[0] && str.substr(i, len) == word){
                    for (int j = i; j < i + len; ++j) {
                        bold[j] = true;
                    }
                }
            }
        }
        
        // str开始添加标签
        std::string res;
        for (int i = 0; i < n; ++i) {
            if(bold[i]){
                if(i == 0 || !bold[i - 1]){
                    res += "<b>";
                }
                res.push_back(str[i]);
                if(i == n || !bold[i + 1]){
                    res += "</b>";
                }
            }else{
                res.push_back(str[i]);
            }
        }
        return res;
    }
};

思路

  • 也可以用HashSet来代替bold数组,只是将需要加粗的位置放入hashSet中。

class Solution {
public:
    string boldWords(vector<string>& words, string str){
        int n = str.size();
        unordered_set<int> bold;
        // 判断每一个word是不是str的子串
        for(auto word : words){
            int len = word.size();
            for (int i = 0; i <= n - len; ++i) {
                if(str[i] == word[0] && str.substr(i, len) == word){
                    for (int j = i; j < i + len; ++j) {
                        bold.insert(j);
                    }
                }
            }
        }

        // str开始添加标签
        std::string res;
        for (int i = 0; i < n; ++i) {
            if(bold.count(i) && !bold.count( i - 1)){
                res += "<b>";
            }
            res.push_back(str[i]);
            if (bold.count(i) && !bold.count(i + 1)){
                res += "</b>";
            }
        }
        return res;
    }
};

trie + 形成区间 + 合并区间

在这里插入图片描述

class Solution {
    class Trie{
    public:
        Trie *next[26] = {nullptr};
        int isEnd = false;
        int count = 0;

        void insert(std::string &s){
            Trie *curr = this;
            for (char i : s) {
                if(curr->next[i - 'a'] == nullptr){
                    curr->next[i - 'a'] = new Trie();
                }
                curr = curr->next[i - 'a'];
            }
            curr->count++;
            curr->isEnd = true;
        }
    };
public:
    string boldWords(vector<string>& words, string str){
        Trie *trie = new Trie(), *curr;
        for(auto &w : words){
            trie->insert(w);
        }

        std::vector<bool> bold(str.size(), false);
        int boldl = 0, boldr=-1;//开始加粗的位置l,r
        for (int i = 0, j; i < str.size(); ++i) {
            curr = trie;
            boldl = max(boldl, i);//加黑的地方左端点
            j = i;
            while (j < str.size() && curr && curr->next[str[j] - 'a']){
                curr = curr->next[str[j] - 'a'];
                if(curr->isEnd){
                    boldr = j;
                }
                j++;
            }
            while(boldl <= boldr)
                bold[boldl++] = true;//标记加黑
        }

        std::string ans;
        for (int i = 0; i < str.size(); ++i) {
            if((i==0 && bold[i]) || (i>0 && !bold[i-1] && bold[i]))//i起点
                ans += "<b>";
            ans += str[i];
            if((i==str.size()-1 && bold[i]) || (i<str.size()-1 && bold[i] && !bold[i+1]))//i是终点
                ans += "</b>";
        }
        return ans;
    }
};

类似题目

类似题目思路
leetcode:56. 将所有重叠的区间合并到一个区间里面 Merge Intervals先按照起始位置排序,然后判断区间是否重叠(start[i] < end) ,如果不重叠,那么压入一个新的区间,否则更新右边界
leetcode: 758. 如果s中有子串在word中出现过,那么在s的那个子串的两端添加标签 bold-words-in-string
leetcode:616. 如果s中有子串在word中出现过,那么在s的那个子串的两端添加标签 Add Bold Tag in String和758题目一模一样,只是758中都是小写字母,而本题没有限制
591. 标签验证器Tag Validator
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值