题解:CF965E Short Code
怎么没有线性做法啊……
建 trie,问题相当于在 trie 上选择深度和尽量小的 \(n\) 个非根节点,使得叶子节点能和其祖先匹配。
一个很自然的想法是贪心地选择深度小的节点,但是会产生多余的节点。
记 \(s_x\) 为 \(x\) 子树内叶子节点的数量。
若选择了一个节点 \(x\),存在 \(x\) 的某个祖先 \(y\),若 \(y\) 子树内选择的节点超过了 \(s_y\) 个,则 \(x\) 无用。
因为 \(y\) 子树内的叶子节点最多就匹配 \(s_y\) 个节点,这个节点肯定多余。
于是在选择 \(x\) 时,若 \(x\) 的某个祖先 \(y\) 子树内已经选择了 \(s_y\) 个节点,则 \(y\) 的子树以后都不会再选择任何节点了,遍历 \(y\) 的子树,打上不可以选择的标记。
遍历到 \(x\) 发现 \(x\) 有标记,说明 \(x\) 整个子树都被打过标记,可以直接退出。
记 \(L\) 为 \(n\) 个字符串的长度和。
每个点最多被打一次标记,打标记复杂度 \(O(L)\)。
注意直接遍历是 \(O(L|\Sigma|)\) 的,每个点压位 \(26\) 个儿子就是 \(O(L)\) 了。
每个选择的 \(x\) 要枚举所有祖先 \(y\),由于所有 \(x\) 的祖先数量和就是答案,答案 \(\le L\),复杂度 \(O(L)\)。
总时间复杂度 \(O(n+L)\),空间复杂度 \(O(L|\Sigma|)\)。

浙公网安备 33010602011771号