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:

  1. words has length in range [0, 50].
  2. words[i] has length in range [1, 10].
  3. S has length in range [0, 500].
  4. All characters in words[i] and S 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
    }
    

All Problems

All Solutions