LeeCode 1984 Trie + 序列化

题意

传送门 LeeCode 1948 删除系统中的重复文件夹

题解

将文件系统建为 T r i e Trie Trie,设根节点深度为 0 0 0,此时有 ∑ u ∈ T r i e u ( d e p t h [ u ] + 1 ) ≤ 2 × 1 0 5 \sum_{u\in Trie}u(depth[u]+1)\leq 2\times 10^5 uTrieu(depth[u]+1)2×105

考虑将子文件夹,即某棵子树序列化。具体而言,后序遍历 T r i e Trie Trie,设以 u u u 为根节点的子树,按照与孩子节点 c h ch ch 连边所代表的字符串 s c h s_{ch} sch 使孩子节点有序,那么可以自定义序列化为
s e r i a l ( u ) = ( s c h 0 , s e r i a l ( c h 0 ) ) ( s c h 1 , s e r i a l ( c h 1 ) ) ⋯   ) serial(u)=(s_{ch_0},serial(ch_0))(s_{ch_1},serial(ch_1))\cdots) serial(u)=(sch0,serial(ch0))(sch1,serial(ch1))) 序列化的子树中包含了子树的信息,可以通过反序列化得到原来的子树。序列化类似于哈希的思想,且保证哈希值对于不同结构子树不会产生冲突。

任一节点仅会出现在其本身与其祖先节点的序列化表示中,那么所有节点的序列化表示规模为 ∑ u ∈ T r i e u ( d e p t h [ u ] + 1 ) ≤ 2 × 1 0 5 \sum_{u\in Trie}u(depth[u]+1)\leq 2\times 10^5 uTrieu(depth[u]+1)2×105。统计序列化表示出现的次数,通过遍历 T r i e Trie Trie 统计答案即可。

class Solution
{
    static const int maxn = 200005;

public:
    int rt, tot;
    map<string, int> trie[maxn];
    string rec[maxn];
    unordered_map<string, int> cnt;
    void insert(vector<string> &vec)
    {
        int p = rt;
        for (auto &u : vec)
        {
            if (trie[p].count(u) == 0)
                trie[p][u] = tot++;
            p = trie[p][u];
        }
    }
    string get_serial(int p)
    {
        string res = "";
        for (auto &pr : trie[p])
            res += '(' + pr.first + ',' + get_serial(pr.second) + ')';
        ++cnt[res];
        return rec[p] = res;
    }
    void dfs(int p, vector<string> &tmp, vector<vector<string>> &res)
    {
        if (cnt[rec[p]] > 1 && rec[p].size() > 0)
            return;
        if (p != rt)
            res.push_back(tmp);
        for (auto &pr : trie[p])
        {
            tmp.push_back(pr.first);
            dfs(pr.second, tmp, res);
            tmp.pop_back();
        }
    }
    vector<vector<string>> deleteDuplicateFolder(vector<vector<string>> &paths)
    {
        tot = 0, rt = tot++;
        for (auto &v : paths)
            insert(v);
        get_serial(rt);
        vector<vector<string>> res;
        vector<string> tmp;
        dfs(rt, tmp, res);
        return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值