题目
给定一个单词列表,我们将这个列表编码成一个索引字符串 S 与一个索引列表 A。
例如,如果这个列表是 ["time", "me", "bell"],我们就可以将其表示为 S = "time#bell#" 和 indexes = [0, 2, 5]。
对于每一个索引,我们可以通过从字符串 S 中索引的位置开始读取字符串,直到 "#" 结束,来恢复我们之前的单词列表。
那么成功对给定单词列表进行编码的最小字符串长度是多少呢?
示例:
输入: words = ["time", "me", "bell"]
输出: 10
说明: S = "time#bell#" , indexes = [0, 2, 5] 。
提示:
- 1 <= words.length <= 2000
- 1 <= words[i].length <= 7
- 每个单词都是小写字母 。
思路一:存储后缀
将所有单词放在set中,对于对于set中每个单词,遍历其后缀,看是否在set中,如果在就删除,比如time,那么就遍历ime, me, e,删除me。这样就保证了set中留下来的单词不可能再合并了,最后遍历set加上每个单词长度和#号。
代码
时间复杂度:O($sum w_{i}^2$),其中 $w_{i}$ 是words[i] 的长度,每个单词有 $w_{i}$ 个后缀,查询其是否在集合中需要进行O($w_{i}$)的哈希值计算。
空间复杂度:O($sum w_{i}$),存储单词的空间开销。
class Solution {
public:
int minimumLengthEncoding(vector<string>& words) {
int res = 0;
unordered_set<string> ust(words.begin(), words.end());
for (string word : ust) {
for (int i = 1; i < word.size(); ++i) {
ust.erase(word.substr(i));
}
}
for (string word : ust) {
res += word.size() + 1;
}
return res;
}
};