Welcome to Subscribe On Youtube
Formatted question description: https://leetcode.ca/all/758.html
758. Bold Words in String
Level
Easy
Description
Given a set of keywords words
and a string S
, make all appearances of all keywords in S
bold. Any letters between <b>
and </b>
tags become bold.
The returned string should use the least number of tags possible, and of course the tags should form a valid combination.
For example, given that words = ["ab", "bc"]
and S = "aabcd"
, we should return "a<b>abc</b>d"
. Note that returning "a<b>a<b>b</b>c</b>d"
would use more tags, so it is incorrect.
Note:
words
has length in range[0, 50]
.words[i]
has length in range[1, 10]
.S
has length in range[0, 500]
.- All characters in
words[i]
andS
are lowercase letters.
Solution
Use an array with type boolean
to determine whether each index should become bold. Find indices of all occurrences of keywords in S
, and set all the indices where the keywords occur to be bold.
Loop over the string S
, and add tags at start and end indices in S
.
-
class Solution { public String boldWords(String[] words, String S) { int length = S.length(); boolean[] bold = new boolean[length]; for (String word : words) { int wordLength = word.length(); int beginIndex = 0; while (beginIndex >= 0) { beginIndex = S.indexOf(word, beginIndex); if (beginIndex >= 0) { for (int i = 0; i < wordLength; i++) bold[beginIndex + i] = true; beginIndex++; } } } StringBuffer sb = new StringBuffer(S); if (bold[length - 1]) sb.append("</b>"); for (int i = length - 1; i > 0; i--) { if (bold[i] && !bold[i - 1]) sb.insert(i, "<b>"); else if (!bold[i] && bold[i - 1]) sb.insert(i, "</b>"); } if (bold[0]) sb.insert(0, "<b>"); String boldStr = sb.toString(); return boldStr; } }
-
class Trie: def __init__(self): self.children = [None] * 128 self.is_end = False def insert(self, word): node = self for c in word: idx = ord(c) if node.children[idx] is None: node.children[idx] = Trie() node = node.children[idx] node.is_end = True class Solution: def boldWords(self, words: List[str], s: str) -> str: trie = Trie() for w in words: trie.insert(w) n = len(s) pairs = [] for i in range(n): node = trie for j in range(i, n): idx = ord(s[j]) if node.children[idx] is None: break node = node.children[idx] if node.is_end: pairs.append([i, j]) if not pairs: return s st, ed = pairs[0] t = [] for a, b in pairs[1:]: if ed + 1 < a: t.append([st, ed]) st, ed = a, b else: ed = max(ed, b) t.append([st, ed]) ans = [] i = j = 0 while i < n: if j == len(t): ans.append(s[i:]) break st, ed = t[j] if i < st: ans.append(s[i:st]) ans.append('<b>') ans.append(s[st : ed + 1]) ans.append('</b>') j += 1 i = ed + 1 return ''.join(ans)
-
class Trie { public: vector<Trie*> children; bool isEnd; Trie() { children.resize(128); isEnd = false; } void insert(string word) { Trie* node = this; for (char c : word) { if (!node->children[c]) node->children[c] = new Trie(); node = node->children[c]; } node->isEnd = true; } }; class Solution { public: string boldWords(vector<string>& words, string s) { Trie* trie = new Trie(); for (string w : words) trie->insert(w); int n = s.size(); vector<pair<int, int>> pairs; for (int i = 0; i < n; ++i) { Trie* node = trie; for (int j = i; j < n; ++j) { int idx = s[j]; if (!node->children[idx]) break; node = node->children[idx]; if (node->isEnd) pairs.push_back({i, j}); } } if (pairs.empty()) return s; vector<pair<int, int>> t; int st = pairs[0].first, ed = pairs[0].second; for (int i = 1; i < pairs.size(); ++i) { int a = pairs[i].first, b = pairs[i].second; if (ed + 1 < a) { t.push_back({st, ed}); st = a, ed = b; } else ed = max(ed, b); } t.push_back({st, ed}); string ans = ""; int i = 0, j = 0; while (i < n) { if (j == t.size()) { ans += s.substr(i); break; } st = t[j].first, ed = t[j].second; if (i < st) ans += s.substr(i, st - i); ans += "<b>"; ans += s.substr(st, ed - st + 1); ans += "</b>"; i = ed + 1; ++j; } return ans; } };
-
type Trie struct { children [128]*Trie isEnd bool } func newTrie() *Trie { return &Trie{} } func (this *Trie) insert(word string) { node := this for _, c := range word { if node.children[c] == nil { node.children[c] = newTrie() } node = node.children[c] } node.isEnd = true } func boldWords(words []string, s string) string { trie := newTrie() for _, w := range words { trie.insert(w) } n := len(s) var pairs [][]int for i := range s { node := trie for j := i; j < n; j++ { if node.children[s[j]] == nil { break } node = node.children[s[j]] if node.isEnd { pairs = append(pairs, []int{i, j}) } } } if len(pairs) == 0 { return s } var t [][]int st, ed := pairs[0][0], pairs[0][1] for i := 1; i < len(pairs); i++ { a, b := pairs[i][0], pairs[i][1] if ed+1 < a { t = append(t, []int{st, ed}) st, ed = a, b } else { ed = max(ed, b) } } t = append(t, []int{st, ed}) var ans strings.Builder i, j := 0, 0 for i < n { if j == len(t) { ans.WriteString(s[i:]) break } st, ed = t[j][0], t[j][1] if i < st { ans.WriteString(s[i:st]) } ans.WriteString("<b>") ans.WriteString(s[st : ed+1]) ans.WriteString("</b>") i = ed + 1 j++ } return ans.String() } func max(a, b int) int { if a > b { return a } return b }