2020CCPC绵阳C题 Code a Trie 字典树(签到题)

Gym102822C Code a Trie: 字典树

链接
传送门: here
题意
建议先浏览一遍题面代码。
给你一段构建字典树的代码:每个节点随机赋予一个权值,保证每个点权值都不相同。
再给你 n ( 1 e 5 ) n(1e5) n(1e5)个字符串及其执行 q u e r y query query函数后的结果,问满足这些结果的字典树最少节点数量。
每组数据字符串长度和不超过 100000 100000 100000

思路
首先将字符串按照权值(即 q u e r y query query后得到的答案)排序并依次插入进字典树。
对于具有相同权值字符串,他们返回答案的节点一定在字典树 r t rt rt l c a lca lca路径上的某点处。
对于只有一个字符串的权值,其 l c a lca lca就是他自己的末尾节点。
将所有权值对应字符串集合的 l c a lca lca标记一下,可以肯定的是每个节点只能作为一种权值的 l c a lca lca

假设有 m m m个字符串权值相同,他们在 l c a lca lca后的出边是: a , b , c , d a,b,c,d a,b,c,d
可以肯定的是这四条出边对应节点的子树内不能有其他权值的 l c a lca lca节点。
我们将 l c a lca lca这些出边对应的节点标记为不可能存在的节点,即 d i e [ n o d e ] = 1 die[node]=1 die[node]=1

确定一下无解情况:

  • 两个字符串相同但是权值不同。
  • 多个权值对应的 l c a lca lca是同一节点。
  • r t rt rt到某个 l c a lca lca路径上存在 d i e die die节点。

再来确定一下 d f s dfs dfs贪心求解过程,遍历到节点 u u u

  • 如果 u u u的某条出边的子树内没有 l c a lca lca节点,这个子树全部扔掉。
  • 如果 u u u的某条出边的子树内有多个 l c a lca lca节点,那么节点 u u u必须保留。
  • 如果 u u u存在若干条出边的子树内仅有 1 1 1 l c a lca lca节点:
    – 如果 u u u l c a lca lca节点,这些子树只需要保留一个节点即可,即 u u u的儿子。
    – 如果 u u u不是 l c a lca lca节点,可以完全抛弃一个子树,剩余子树处理同上。

为什么这样贪心是对的呢?一条条解答:

  • 这条出边子树内没有 l c a lca lca节点,我的 q u e r y query query不会走到这里,当然可以全部抛弃掉呀。
  • 如果节点 u u u不保留,代表 u u u的子树都不保留,那这对应两个 l c a lca lca q u e r y query query势必会得到同一个答案才对,互相矛盾,所以 u u u必须保留。
  • 这里分了两个情况:
    – 这些子树内只有一个 l c a lca lca节点,那么我询问的时候提前结束肯定最优,也不会影响别人,所以只需要保留 u u u的儿子。
    – 因为 u u u不是 l c a lca lca,我可以把一个子树内的 l c a lca lca节点直接提到 u u u来。

o v e r ! over! over!稍微复杂点的签到题罢了。

备注
下标写错找了一年bug。

godie(st[sid[j]], len[sid[j]]);
---->
godie(st[j], len[j]);
想die哦。

AC_CODE
思路很简单,可惜我代码写的有点冗杂。
here

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值