1. 程式人生 > >[LeetCode] Add Bold Tag in String 字串中增新增粗標籤

[LeetCode] Add Bold Tag in String 字串中增新增粗標籤

Given a string s and a list of strings dict, you need to add a closed pair of bold tag <b> and </b> to wrap the substrings in s that exist in dict. If two such substrings overlap, you need to wrap them together by only one pair of closed bold tag. Also, if two substrings wrapped by bold tags are consecutive, you need to combine them.

Example 1:

Input: 
s = "abcxyz123"
dict = ["abc","123"]
Output:
"<b>abc</b>xyz<b>123</b>"

Example 2:

Input: 
s = "aaabbcc"
dict = ["aaa","aab","bc"]
Output:
"<b>aaabbc</b>c"

Note:

  1. The given dict won't contain duplicates, and its length won't exceed 100.
  2. All the strings in input have length in range [1, 1000].

這道題給我們了一個字串,還有一個字典,讓我們把字串中在字典中的單詞加粗,注意如果兩個單詞有交集或者相接,就放到同一個加粗標籤中。博主剛開始的想法是,既然需要匹配字串,那麼就上KMP大法,然後得到每個單詞在字串匹配的區間位置,然後再合併區間,再在合併後的區間兩頭加標籤。但是一看題目難度,Medium,中等難度的題不至於要祭出KMP大法吧,於是去網上掃了一眼眾神們的解法,發現大多都是暴力匹配啊,既然OJ能過去,那麼就一起暴力吧。這題參考的是高神shawngao的解法,高神可是集了一千五百多個讚的男人,叼到飛起!思路是建一個和字串s等長的bold布林型陣列,表示如果該字元在單詞裡面就為true,那麼最後我們就可以根據bold陣列的真假值來新增標籤了。我們遍歷字串s中的每一個字元,把遍歷到的每一個字元當作起始位置,我們都匹配一遍字典中的所有單詞,如果能匹配上,我們就用i + len來更新end,len是當前單詞的長度,end表示字典中的單詞在字串s中結束的位置,那麼如果i小於end,bold[i]就要賦值為true了。最後我們更新完bold陣列了,就再遍歷一遍字串s,如果bold[i]為false,直接將s[i]加入結果res中;如果bold[i]為true,那麼我們用while迴圈來找出所有連續為true的個數,然後在左右兩端加上標籤,參見程式碼如下:

解法一:

class Solution {
public:
    string addBoldTag(string s, vector<string>& dict) {
        string res = "";
        int n = s.size(), end = 0;
        vector<bool> bold(n, false);
        for (int i = 0; i < n; ++i) {
            for (string word : dict) {
                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;
    }
};

這道題跟之後的那道Bold Words in String是一模一樣的題,那麼解法當然是可以互通的了,這裡我們把那道題中解法二也貼過來吧,由於解法一和解法二實在是太相似了,就貼一個吧,具體講解可以參見Bold Words in String這篇帖子,參見程式碼如下:

解法二:

class Solution {
public:
    string addBoldTag(string s, vector<string>& dict) {
        string res = "";
        int n = s.size();
        unordered_set<int> bold;
        for (string word : dict) {
            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 += s[i];
            if (bold.count(i) && !bold.count(i + 1)) res += "</b>";
        }
        return res;
    }
};

類似題目:

參考資料: