Codeforces 590 E
https://codeforces.com/problemset/problem/590/E
给 $ n $ 个只包含字符 $ a $ 和 $ b $ 的字符串,总长度不超过 $ 10^7 $,选出最多的字符串,使得其中不存在字符串 $ a $ 和 $ b $ 满足 $ a $ 是 $ b $ 的子串,输出方案,如果有多种方案,输出任意一种
$ n \le 750 $
我们需要对每个串求出所有的比它短的是它的子串的字符串,并向其连边,可以发现这 $ n $ 个点形成了若干个 DAG
对所有字符串建出 AC 自动机,每个节点记录一个 $ id $,表示当前节点的子串中是 $ n $ 个字符串中的最长的一个字符串的下标,再对每个串求出比它短的是它的子串的字符串,进行 floyd 传递闭包使得所有的不能放在一起的字符串均被求出
这个方法很巧妙,求出了每个节点在 DAG 上的后继再进行传递闭包,防止了匹配过程中跳 $ fail $ 指针次数过多,同时保证了正确性
如果把所有的边看成无向边,我们要求的就是这张图的最大独立集,直接做是指数级的,这个时候我们引入一些东西
偏序集:给定集合 $ S $ ,$ \le $ 是 $ S $ 上的二元关系,$ \le $ 要满足
- 自反性:$ \forall a \subseteq S $ 有 $ a \le a $
- 反对称性:$ \forall a, b \subseteq S, a \le b $ 且 $ b \le a $ 则 $ a = b $
- 传递性:$ \forall a, b, c \subseteq S, a \le b $ 且 $ b \le c $ 则 $ a \le c $
则称 $ \le $ 为 $ S $ 上的偏序关系,$ (S, \le) $ 是偏序集
可以发现偏序集形成若干 DAG,DAG 也可以形成偏序集
全序集:设 $ (S, \le) $ 是偏序集,如果 $ \forall a, b \subseteq S $ , $ a \le b $ 和 $ b \le a $ 中至少有一个成立,则称 $ \le $ 为序关系,$ (S, \le) $ 是全序集
可以发现全序集形成一个 DAG,而且是一个团
以下的偏序关系均为 $ \le $
链:全序集
反链:设 $ S $ 是偏序集,如果 $ \forall a, b \subseteq S $ , $ a $ 和 $ b $ 无法比较,则称 $ S $ 为反链
可以发现题目要求的就是最大反链的元素个数
Dilworth 定理:偏序集能划分成的最少的全序集的个数与最大反链的元素个数相等
偏序集能划分成的最少的全序集的个数,又因为每一个全序集都是链,所以题目转换为了 DAG 上的最小路径可重复点覆盖
DAG 上的最小路径可重复点覆盖需要传递闭包绕点 ( 具体可看这篇博客 ),我们最开始已经传递过闭包了,所以并不需要再做一次
然而这题还需要输出方案
考虑一下我们传递闭包后,每一条路径的开头的那个点,它和这条路径中的所有点都有偏序关系 ( $ \forall p \le p_1 $ )
我们把这些点放在一起,就形成了一条反链(如果不是反链,根据传递性,一定有两条路径可以合并成一条
所以我们把开头的这个点提出来(在算法中是二分图匹配里未被匹配的点)输出即可
原文地址:https://www.cnblogs.com/LJC00118/p/10807261.html