[LeetCode] Bold Words in String 字串中的加粗單詞
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"]
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]
S
are lowercase letters.
這道題跟之前的那道Add Bold Tag in String是一模一樣的,之前還換個馬甲,這次連場景都不換了,直接照搬啊?!我也是服氣的~這道題應該沒有太多的技巧,就是照題目意思來就行了,我們使用一個數組bold,標記所有需要加粗的位置為true,初始化所有為false。我們首先要判斷每個單詞word是否是S的子串,判斷的方法就是逐個字元比較,遍歷字串S,找到和word首字元相等的位置,並且比較隨後和word等長的子串,如果完全相同,則將子串所有的位置在bold上比較為true。等我們知道了所有需要加粗的位置後,我們就可以來生成結果res了,我們遍歷bold陣列,如果當前位置是true的話,表示需要加粗,那麼我們首先看如果是第一個字元,或者其前面的字元不用加粗,我們加上一個左標籤<b>,然後我們將當前字元加入結果res中,然後再判斷,如果當前是末尾字元,或者後面一個字元不用加粗,則需要加上一個右標籤</b>;如果當前位置是false,我們直接將字元加入結果res中即可,參見程式碼如下:
解法一:
class Solution { public: string boldWords(vector<string>& words, string S) { int n = S.size(); string res = ""; vector<bool> bold(n, false); for (string word : words) { int len = word.size(); for (int i = 0; i <= n - len; ++i) { if (S[i] == word[0] && S.substr(i, len) == word) { for (int j = i; j < i + len; ++j) bold[j] = true; } } } for (int i = 0; i < n; ++i) { if (bold[i]) { if (i == 0 || !bold[i - 1]) res += "<b>"; res.push_back(S[i]); if (i == n - 1 || !bold[i + 1]) res += "</b>"; } else { res.push_back(S[i]); } } return res; } };
我們可以用HashSet來代替陣列,只是將需要加粗的位置放入HashSet,然後我們在生成結果res的時候,先檢測當前位置是否加粗,如果加粗了,並且前一個位置不在HashSet中,這樣就不用判斷是否是第一個元素了,因為i-1肯定不再HashSet中,也不像陣列那樣存在越界的可能,我們給結果res加上左標籤,然後將當前的字元加入結果res中,然後再判斷如果當前位置如果加粗了,並且下一個位置不在HashSet中,我們給結果res加上右標籤,參見程式碼如下:
解法二:
class Solution { public: string boldWords(vector<string>& words, string S) { int n = S.size(); string res = ""; unordered_set<int> bold; for (string word : words) { int len = word.size(); for (int i = 0; i <= n - len; ++i) { if (S[i] == word[0] && S.substr(i, len) == word) { for (int j = i; j < i + len; ++j) bold.insert(j); } } } for (int i = 0; i < n; ++i) { if (bold.count(i) && !bold.count(i - 1)) res += "<b>"; res.push_back(S[i]); if (bold.count(i) && !bold.count(i + 1)) res += "</b>"; } return res; } };
前面提到了這道題跟Add Bold Tag in String是完全一樣,那麼當然二者的解法是互通的,下面的解法是之前那道題中的解法,其實整體思路是一樣的,只不過在構建的bold陣列的時候,是先遍歷的字串S,而不是先遍歷的單詞。對於字串S中的每個字元為起點,我們都遍歷下所有單詞,如果某個單詞是以當前字元為起點的子串的話,那麼我們用i+len來更新end,所以遍歷完所有單詞後,只要當前位置需要加粗,那麼end一定大於i,通過這種方法同樣也可以生成正確的bold陣列。然後在建立結果res字串的時候也跟上面的方法有些不同,首先判斷,如果當前未被加粗,那麼將當前字元存入結果res中並且continue,否則開始找相連的需要加粗的位置,用j來指向下一個不用加粗的位置,這樣中間的子串就可以放入標籤中整體加到res中,然後繼續在後面查詢連續加粗的子串,參見程式碼如下:
解法三:
class Solution { public: string boldWords(vector<string>& words, string S) { int n = S.size(), end = 0; string res = ""; vector<bool> bold(n, false); for (int i = 0; i < n; ++i) { for (string word : words) { int len = word.size(); if (i + len <= n && S.substr(i, len) == word) { end = max(end, i + len); } } bold[i] = end > i; } for (int i = 0; i < n; ++i) { if (!bold[i]) { res.push_back(S[i]); continue; } int j = i; while (j < n && bold[j]) ++j; res += "<b>" + S.substr(i, j - i) + "</b>"; i = j - 1; } return res; } };
類似題目:
參考資料: