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;
}
};

猜你喜欢

转载自blog.csdn.net/qq_26410101/article/details/82945031