【UOJ772】【UER11】企鹅游戏(复杂度分析)

题意:

给定 \(n\) 个不同的字符串 \(s_1,\cdots,s_n\)\(m\) 次询问,每次给出字符串 \(t\),对所有在 \(t\) 中出现的 \(s_i\) 求出其出现次数,并用题目指定的 Hash 方式得到一个结果并返回。

\(\sum |s_i|,\sum |t_j|\leq L=10^6\)

题解:

即我们得找出每个在 \(t\) 中出现的 \(s_i\) 并单独地统计它们的出现次数。

我们先估计有多少个 \(s_i\)\(t\) 中出现了。一个初步的估计是:注意到 \(s_1,\cdots,s_n\) 共有 \(\sqrt L\) 种不同的长度,那么以 \(t\) 中某固定位置结尾的 \(s_i\) 有至多 \(\sqrt L\) 个,那么所有 \(s_i\)\(t\) 中的出现次数至多为 \(|t|\sqrt L\)

根据上述推导我们可以得到一个做法:建出 \(s_i\) 的 AC 自动机,我们只需对每个节点记录其 fail 树的祖先中最近的出现的 \(s_i\),然后每次用 \(t\) 在 AC 自动机上走并对经过的每个节点暴力向上跳出现过的 \(s_i\) 并贡献即可。时间复杂度 \(O(L\sqrt L)\)


一个更精细的界是:考虑长度 \(\leq B\) 的所有 \(s_i\),根据类似地推导我们可以知道它们至多有 \(B|t|\) 个出现过;而对于长度 \(>B\) 的所有 \(s_i\),首先它们只有 \(L/B\) 个,其次,它们会在某个 \(t_j\) 中出现当且仅当 \(|t_j|\geq B\),所以只有 \(L/B\) 个可能的 \(t_j\),于是所有 \(t_j\) 的出现过的这种 \(s_i\) 的数量的和不超过 \((L/B)^2\)。取 \(B=L^{1/3}\) 发现所有 \(t_j\) 的出现过的 \(s_i\) 的数量和不超过 \(L^{4/3}\)

第一个分析给出的是所有 \(s_i\)\(t\) 中出现次数的和的界,而第二个分析给出的是在 \(t\) 中出现过的 \(s_i\) 的数量的界。

那我们考虑对于 \(t\) 在 AC 自动机上经过的点先暴力往上跳,如果之前跳过了我们就不必跳了。据此建出一棵以 \(t\) 的每个前缀、以及所有在 \(t\) 中出现的 \(s_i\) 为关键点的虚树(注意不是严格的虚树,比如一些 lca 我们没建出来,但它们是不重要的),然后在这棵树上 DP 即可。

时间复杂度 \(O(L^{3/4})\)

通过如下构造可以证明第二个界是紧的:构造 \(t\),其每个字符都不同,且 \(|t|=L^{1/3}\)。把 \(t\) 的所有子串当成 \(s_1,\cdots,s_n\),那么 \(n=O(L^{2/3})\)\(\sum s_i=O(L)\)。那么每个 \(s_i\) 都在 \(t\) 中出现过,从而如果我们每次都询问 \(t\) 的话,总共的出现过的 \(s_i\) 的数量为 \(O(L^{4/3})\)

由此可以看出如何猜出 \(O(L^{4/3})\) 的上界:假设我们要卡这个次数,显然是每次都问相同的串 \(t\),而显然所有 \(s_i\) 都在 \(t\) 中出现时最优的,而显然我们会将 \(s_i\) 设置为 \(t\) 的小于等于某个 \(K\) 的所有子串,共 \(K|t|\) 个,长度总和为 \(K^2|t|\)。那么问题转为,在 \(K^2|t|\leq L\)\(K\leq |t|\) 的前提下,如何使得 \(K|t|\cdot \frac{L}{|t|}\) 最大。那么显然是取 \(K=|t|=L^{1/3}\)。然后再想如何严格地证明。


更进一步分析在于利用不同查询时的重复的信息。设 \(v_{i,c}\) 表示 \(s_i\) 的出现次数为 \(c\) 时对答案的贡献。那么所有查询可以看成是 \(O(L)\) 次给定 \(c\),问 fail 树上(注意这里的 fail 树是缩化成只包含所有 \(s_i\) 的终止点)一条链的 \(v_{i,c}\) 的和(注意一次询问形成的虚树只包含 \(O(|t|)\) 个叶子)。

我们之前的方法是每次暴力跳这条链并统计答案,这样有可能会重复地跳很多次。考虑将所有询问离线并按 \(c\) 分类,对固定的 \(c\),找出所有询问的链的并,且在它们的并上预处理树上前缀和,然后询问时直接两个前缀和相减即可。

考虑这么做的时间复杂度,其实就是每个 \(s_i\) 在所有 \(t_j\) 中的出现次数去重后的数量之和。设 \(a_i\) 表示长度为 \(i\) 的串的数量,那么 \(\sum_i i\times a_i\leq L\)。对于某一固定的长度 \(i\),这 \(s=a_i\) 个串在所有 \(t_j\) 中的总出现次数之和不超过 \(L\),相当于一个矩阵 \(x_{i,j}\),其中 \(i\in [1,s]\)、所有元素和不超过 \(L\),要求所有行的本质不同的数的数量之和最大。那么当一行的和 \(y_i\) 确定时,贡献也就确定了为 \(\sqrt{y_i}\)。所以现在是要 \(\sum y_i=L\)\(\sum\sqrt{y_i}\) 最大。

\(f(y_1,\cdots,y_s)=\sum_{i}{\sqrt{y_i}}\),当在点 \(\vec a=(y_1',\cdots,y_s')\) 是最优解时(这里放宽限制考虑 \(y_i\) 可取任意非负实数的情况),该点向 \(y_1,\cdots,y_s\) 的偏导应该都相等,否则不妨设 \(\frac{\partial f}{\partial y_1}(\vec a)>\frac{\partial f}{\partial y_2}(\vec a)\),那么记 \(\vec v=(\frac{\sqrt 2}{2},-\frac{\sqrt 2}{2},0,\cdots,0)\),根据偏导计算公式有 \(\nabla_{\vec v}f(\vec a)=\nabla f(\vec a)\cdot\vec v>0\),那么可以将 \(\vec a\)\(\vec v\) 方向微移一点,此时 \(\sum y_i'\) 不变且 \(f(\vec a)\) 严格变大。结合 \(\frac{\partial f}{\partial y_i}=\frac{1}{2\sqrt{y_i}}\),得到 \(y_1=\cdots=y_s\),而 \(\sum\sqrt{y_i}\) 的最大值是存在的,所以这就是充要条件。于是得到 \(\sum\sqrt{y_i}\) 的最大值为 \(s\sqrt{\frac{L}{s}}=\sqrt{Ls}\)

现在问题变成了,要 \(\sum_ii\times a_i=L\)\(\sum_i\sqrt{La_i}\) 最大。采用类似的方法,记 \(b_i=i\times a_i\),设 \(g(b_1,\cdots,b_L)=\sum_i\sqrt{\frac{b_i}{i}}\),并得到 \(\frac{\partial g}{\partial b_i}\) 应该都相等,结合 \(\frac{\partial g}{\partial b_i}=\frac{1}{2\sqrt{ib_i}}\) 可知应当存在 \(k\) 使得 \(b_i=\frac{k}{i}\),结合 \(\sum_i b_i=L\) 解得 \(k=O(\frac{L}{\log L})\)\(b_i=O(\frac{L}{i\log L})\)\(a_i=O(\frac{L}{i^2\log L})\),此时 \(\sum_i\sqrt{a_i}=O(\sqrt{\frac{L}{\log L}}\sum_i\frac{1}{i})=O(\sqrt{L\log L})\),所以总复杂度 \(O(L\sqrt{\log L})\)

然后建虚树要线性(全部离线下来桶排 + \(O(1)\) lca)。

posted @ 2022-11-20 15:09  ez_lcw  阅读(92)  评论(0编辑  收藏  举报