820. 单词的压缩编码
给定一个单词列表,我们将这个列表编码成一个索引字符串 S 与一个索引列表 A。
例如,如果这个列表是 [“time”, “me”, “bell”],我们就可以将其表示为 S = “time#bell#” 和 indexes = [0, 2, 5]。
对于每一个索引,我们可以通过从字符串 S 中索引的位置开始读取字符串,直到 “#” 结束,来恢复我们之前的单词列表。
那么成功对给定单词列表进行编码的最小字符串长度是多少呢?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/short-encoding-of-words
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
示例:
输入: words = ["time", "me", "bell"]
输出: 10
说明: S = "time#bell#" , indexes = [0, 2, 5] 。
提示:
1 <= words.length <= 2000
1 <= words[i].length <= 7
每个单词都是小写字母 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/short-encoding-of-words
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。方法一:暴力破解
class Solution {
public:
int minimumLengthEncoding(vector<string>& words) {
unordered_set<string> good(words.begin(), words.end());
for(auto v:good){
for(int i = 1;i<v.length();i++){
string s = v.substr(i);
cout<<s<<endl;
good.erase(s);
}
}
int sum = 0;
for(auto v:good){
sum+=(v.length()+1);
}
return sum;
}
};
方法二,字典树
字典树,倒序插入,然后遍历树,判断最后一个节点的长度,每个叶子节点长度加一的和为答案.
int sum = 0;
int cnt = 0;
struct node{
int data[27];
void init(){
for(int i = 0;i<26;i++){
data[i]=-1;
}
}
}tree[140000+50];
void buildtree(string s){
int p= 0;
for(int i = s.length()-1 ; i>=0 ; i--){
int x = s[i]-'a';
if(tree[p].data[x]==-1){
tree[p].data[x]=++cnt;
tree[cnt].init();
}
p = tree[p].data[x];
}
}
bool check(int n){ //判断是否是叶子节点
for(int i = 0;i<26;i++){
if(tree[n].data[i]!=-1){
return false;
}
}
return true;
}
void dfs(int n,int ans){
if(check(n)){
sum+=(ans+1);
return ;
}
for(int i = 0;i<26;i++){
if(tree[n].data[i]!=-1){
dfs(tree[n].data[i],ans+1); //dfs遍历
}
}
}
class Solution {
public:
int minimumLengthEncoding(vector<string>& words) {
cnt = 0;
sum = 0;
tree[cnt].init();
for(auto v:words){
buildtree(v);
}
dfs(0,0);
return sum;
}
};