题目描述
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/short-encoding-of-words
给定一个单词列表,我们将这个列表编码成一个索引字符串 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容器去重,然后遍历每个列表中每个单词的所有后缀(word.substr(k)),对于每个后缀,如果set中存在就把其删除。 t.erase(word.substr(k));。最后set中剩下的就是没有重复也没有跟别的单词后缀相同的。每个单词长度加上#的总和就是答案了
代码
class Solution {
public:
int minimumLengthEncoding(vector<string>& words) {
unordered_set<string> t(words.begin(),words.end());
for(const string& word : words){
for(int k = 1; k <= word.size(); k++){
t.erase(word.substr(k));
}
}
int ans = 0;
for(const string& word : t){
ans += word.size() + 1;
}
return ans;
}
};
思路二
字典树
比如题目例子
代码
class TrieNode{
TrieNode* children[26];
public:
int count;
TrieNode(){
for(int i = 0; i < 26; i++){
children[i] = NULL;
count = 0;
}
}
TrieNode* get(char c){
if(children[c - 'a'] == NULL){
children[c - 'a'] = new TrieNode();
count++;
}
return children[c - 'a'];
}
};
class Solution {
public:
int minimumLengthEncoding(vector<string>& words) {
TrieNode* trie = new TrieNode();
unordered_map<TrieNode*,int> nodes;
for(int i = 0; i < words.size(); i++){
string word = words[i];
TrieNode* current = trie;
for(int j = word.length()-1; j >=0; j--){
current = current -> get(word[j]);
}
nodes[current] = i;
}
int ans = 0;
for(auto& [node, idx] : nodes){
if(node -> count ==0){
ans += words[idx].length() + 1;
}
}
return ans;
}
};