1. 程式人生 > >[LeetCode] Bold Words in String 字串中的加粗單詞

[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"]

 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.

這道題跟之前的那道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;
    }
};

類似題目:

參考資料: