Input: s ="abcxyz123", words =["abc","123"]Output: "<b>abc</b>xyz<b>123</b>"Explanation: The two strings of words are substrings of s as following:"abcxyz123".We add <b> before each substring and </b> after each substring.
Input: s ="aaabbb", words =["aa","b"]Output: "<b>aaabbb</b>"Explanation:
"aa" appears as a substring two times:"aaabbb" and "aaabbb"."b" appears as a substring three times:"aaabbb","aaabbb", and "aaabbb".We add <b> before each substring and </b> after each substring:"<b>a<b>a</b>a</b><b>b</b><b>b</b><b>b</b>".Since the first two <b>'s overlap, we merge them:"<b>aaa</b><b>b</b><b>b</b><b>b</b>".Since now the four <b>'s are consecutive, we merge them:"<b>aaabbb</b>".
We want to bold all substrings in s that match any word in words. Overlapping or consecutive matches should be merged into a single bold region. By marking all characters that should be bolded, then merging consecutive marked regions, we can efficiently build the result.
classSolution {
public: string addBoldTag(string s, vector<string>& words) {
int n = s.size();
vector<bool> bold(n, false);
for (const string& w : words) {
size_t pos = s.find(w, 0);
while (pos != string::npos) {
for (int i = pos; i < pos + w.size(); ++i) bold[i] = true;
pos = s.find(w, pos +1);
}
}
string ans;
for (int i =0; i < n; ++i) {
if (bold[i] && (i ==0||!bold[i-1])) ans +="<b>";
ans += s[i];
if (bold[i] && (i == n-1||!bold[i+1])) ans +="</b>";
}
return ans;
}
};
classSolution {
public String addBoldTag(String s, String[] words) {
int n = s.length();
boolean[] bold =newboolean[n];
for (String w : words) {
int idx = s.indexOf(w);
while (idx !=-1) {
for (int i = idx; i < idx + w.length(); i++) bold[i]=true;
idx = s.indexOf(w, idx + 1);
}
}
StringBuilder ans =new StringBuilder();
for (int i = 0; i < n; i++) {
if (bold[i]&& (i == 0 ||!bold[i-1])) ans.append("<b>");
ans.append(s.charAt(i));
if (bold[i]&& (i == n-1 ||!bold[i+1])) ans.append("</b>");
}
return ans.toString();
}
}
classSolution {
funaddBoldTag(s: String, words: Array<String>): String {
val n = s.length
val bold = BooleanArray(n)
for (w in words) {
var idx = s.indexOf(w)
while (idx != -1) {
for (i in idx until idx + w.length) bold[i] = true idx = s.indexOf(w, idx + 1)
}
}
val ans = StringBuilder()
for (i in0 until n) {
if (bold[i] && (i ==0|| !bold[i-1])) ans.append("<b>")
ans.append(s[i])
if (bold[i] && (i == n-1|| !bold[i+1])) ans.append("</b>")
}
return ans.toString()
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
classSolution:
defaddBoldTag(self, s: str, words: list[str]) -> str:
n = len(s)
bold = [False] * n
for w in words:
start = s.find(w)
while start !=-1:
for i in range(start, start + len(w)):
bold[i] =True start = s.find(w, start +1)
ans = []
for i in range(n):
if bold[i] and (i ==0ornot bold[i-1]):
ans.append("<b>")
ans.append(s[i])
if bold[i] and (i == n-1ornot bold[i+1]):
ans.append("</b>")
return''.join(ans)
impl Solution {
pubfnadd_bold_tag(s: String, words: Vec<String>) -> String {
let n = s.len();
letmut bold =vec![false; n];
let s_bytes = s.as_bytes();
for w in&words {
let w_bytes = w.as_bytes();
for i in0..=n-w.len() {
if&s_bytes[i..i+w.len()] == w_bytes {
for j in i..i+w.len() {
bold[j] =true;
}
}
}
}
letmut ans = String::new();
let s_chars: Vec<char>= s.chars().collect();
for i in0..n {
if bold[i] && (i ==0||!bold[i-1]) {
ans.push_str("<b>");
}
ans.push(s_chars[i]);
if bold[i] && (i == n-1||!bold[i+1]) {
ans.push_str("</b>");
}
}
ans
}
}
⏰ Time complexity: O(n * m * k) where n is the length of s, m is the number of words, and k is the average length of words (since for each word, we scan s for all occurrences).
🧺 Space complexity: O(n) for the bold array and output string.