1. 程式人生 > >Replace Words 單詞替換

Replace Words 單詞替換

在英語中,我們有一個叫做 詞根(root)的概念,它可以跟著其他一些片語成另一個較長的單詞——我們稱這個詞為 繼承詞(successor)。例如,詞根an,跟隨著單詞 other(其他),可以形成新的單詞 another(另一個)。

現在,給定一個由許多詞根組成的詞典和一個句子。你需要將句子中的所有繼承詞詞根替換掉。如果繼承詞有許多可以形成它的詞根,則用最短的詞根替換它。

你需要輸出替換之後的句子。

示例 1:

輸入: dict(詞典) = ["cat", "bat", "rat"]
sentence(句子) = "the cattle was rattled by the battery"
輸出:
"the cat was rat by the bat"

注:

  1. 輸入只包含小寫字母。
  2. 1 <= 字典單詞數 <=1000
  3. 1 <=  句中詞語數 <= 1000
  4. 1 <= 詞根長度 <= 100
  5. 1 <= 句中詞語長度 <= 1000

思路:這道題用單詞字首樹來做,但是題目要求如果有多個解,保留最短的單詞長度即可,所以有兩個優化的地方:

1:每次通過bool變數的isRoot來匹配是否存在最短路徑,例如cat和cata同時作為詞根進入字首樹,那麼字首樹只會構造出cat而不會構造出cata(嚴格來說和cat和cata誰先進入有關係,但是最終的結果是通過isRoot變數來保證在查詢匹配字串時只匹配cat)

2:如果沒有找到以當前單詞為詞根的字串,那麼游標會持續向右移,所以這樣可以保證時間複雜度是O(1)

參考程式碼:

class Solution {
public:
class trie {
private:
	bool isRoot=false;
	trie* l[26] = {};
public:
	void insert(string& word, int start, int end) {
		isRoot |= (start == end);
		if (!isRoot) {
			if (l[word[start] - 'a'] == nullptr) l[word[start] - 'a'] = new trie();
			l[word[start] - 'a']->insert(word, start + 1, end);
		}
	}
	int calculate(string& word, int start, int ch, int end) {
		if ((start+ch)==end || word[start+ch]==' ' || isRoot) return ch;
		if (l[word[start + ch] - 'a'] == nullptr) {   //沒有找到root
			while ((start + ch) < end && word[start + ch] != ' ') ch++;
			return ch;
		}
		return l[word[start + ch] - 'a']->calculate(word, start, ch + 1, end);
	}
};
string replaceWords(vector<string>& dict, string sentence) {
	trie t;
	string res;
	for (auto &tmp : dict) t.insert(tmp,0,tmp.size());
	for (int i = 0; i < sentence.size();) {
		if (sentence[i] == ' ') res += sentence[i++];
		int tmp = t.calculate(sentence, i, 0, sentence.size());
		res += sentence.substr(i, tmp);
		for (i += tmp; i < sentence.size() && sentence[i] != ' ';) i++;
	}
	return res;
}
};