Leetcode 单词的压缩编码(字典树)

题目描述:

  给定一个单词列表,我们将这个列表编码成一个索引字符串 S 与一个索引列表 A。例如,如果这个列表是 ["time", "me", "bell"],我们就可以将其表示为 S = "time#bell#" 和 indexes = [0, 2, 5]。

对于每一个索引,我们可以通过从字符串 S 中索引的位置开始读取字符串,直到 "#" 结束,来恢复我们之前的单词列表。那么成功对给定单词列表进行编码的最小字符串长度是多少呢?

 

题解:

  分析题目可知能够进行压缩的字符串的特征--为其他字符串的后缀。考虑建立一个字典树,为了确定不同的单词具有相同的后缀,我们可以将其反序之后插入字典树中。例如,我们有 "time" 和 "me",可以将 "emit" 和 "em" 插入字典树中。图示如下:

  

 

   然后,字典树的叶子节点(没有孩子的节点)就代表没有后缀的单词,统计叶子节点代表的单词长度加一的和即为我们要的答案。(参考自:https://leetcode-cn.com/problems/short-encoding-of-words/solution/dan-ci-de-ya-suo-bian-ma-by-leetcode-solution/

 

AC代码:

  

class TrieNode{
    TrieNode* child[26];
public:
    int count; // 是否为叶子节点
    TrieNode()
    {
        for(int i=0;i<26;i++) child[i] = NULL;
        count = 0;
    }
    
    TrieNode* get(char c) // 或许字符c对应的child节点
    {
        if(child[c-'a'] == NULL) 
        {
            child[c-'a'] = new TrieNode();
            count++;
        }
        return child[c-'a'];
        
    }
};


class Solution {
public:
    TrieNode* insert(TrieNode* root,string s)
    {
        int Len = s.size();
        // 倒插
        for(int i=Len-1;i>=0;i--)
        {
            root = root->get(s[i]);
        }
        return root;
    } 

    int minimumLengthEncoding(vector<string>& words) {
        int Len = words.size();
        TrieNode* trie = new TrieNode();
        node.clear();
        for(int i=0;i<Len;i++)
        {
            string word = words[i];
            TrieNode* leaf = insert(trie,word);
            node[leaf] = i;
        }
        int ans = 0;
        // map 的遍历方式
        for(auto [node,idx]:node)
        {
            if(node->count == 0) ans += (words[idx].size()+1);
        }
        return ans;
    }

private:
    unordered_map<TrieNode*,int> node;
};

 

posted @ 2020-03-31 12:12  猪突猛进!!!  阅读(416)  评论(0编辑  收藏  举报