The 2020 ICPC Asia Macau Regional Contest B Boring Problem

Posted Dreamunk

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了The 2020 ICPC Asia Macau Regional Contest B Boring Problem相关的知识,希望对你有一定的参考价值。

比较模板的题。

题目
给定一个字符串 \\(S\\)\\(n\\) 个字符串 \\(T_1,T_2,\\dots,T_n\\),每个串长度都是 \\(m\\),一个长度为 \\(k\\) 的有理数序列 \\(p_1,p_2,\\dots,p_k\\) 保证 \\(\\sum p_i=1\\)。每个字符串由前 \\(k\\) 个小写字母构成。
我们进行下面的过程:

  1. 如果存在 \\(j(1\\le j\\le n)\\) 满足 \\(T_j\\)\\(S\\) 的子串,那么停止这个过程。
  2. 否则按 \\(p_i\\) 的概率将第 \\(i\\) 个小写字母加到 \\(S\\) 的末尾,然后继续这个过程。

定义 \\(f(S,T,p)\\) 表示停止的时候 \\(S\\) 的期望长度。
给一个字符串 \\(R\\),对 \\(R\\) 的每个前缀,求出答案。也就是求出 \\(f(R[1\\dots i],T,p)\\)\\(i\\in [1,|R|]\\) 的所有值。
\\(n\\le 100,nm\\le 10000,|R|\\le 10^4\\),答案对 \\(1\\ 000\\ 000\\ 007 取模\\)

题解:

一个显然的做法是建出 \\(T_1,T_2,\\cdots,T_n\\) 的 AC 自动机,则题目相当于在 AC 自动机上随机游走,问走到叶结点之一的期望次数。

\\(E(x_i)\\) 表示从 AC 自动机上第 \\(i\\) 个点出发,期望多少次能走到一个叶结点,列方程后高斯消元即得答案。未知数个数达到 \\(O(nm)\\),时间复杂度 \\(O(n^3m^3)\\),过不了。


考虑优化未知数个数。观察方程 \\(E(x_u)=1+\\sum_{c=1}^k p_c E(x_{\\operatorname{next}_{u,c}})\\)

\\(\\operatorname{next}_{u,c}\\) 表示从点 \\(u\\)\\(c\\) 的转移边到的结点)中,\\(\\operatorname{next}_{u,c}\\) 要么是 Trie 树上 \\(u\\) 的儿子,要么深度不超过 \\(u\\) 的深度。

考虑树剖:对每个点 \\(u\\) 任选一个儿子 \\(v\\) 作为偏爱儿子进行树链剖分。那这个方程就可以看作把 \\(v\\)\\(u\\) 的其他儿子和深度不超过 \\(u\\) 的深度的结点表示出来。

那么我们发现经过代入,每个结点的答案都可以通过一些链顶结点的答案来表示。怎么做呢?我们按从浅到深的顺序来做。注意到对一个方程 \\(E(x_u)=1+\\sum_{c=1}^k p_c E(x_{\\operatorname{next}_{u,c}})\\),它所涉及到的最深层的结点是 \\(u\\) 的全部儿子,而它们除了偏爱儿子 \\(v\\) 以外全是链顶结点。而对于所涉及到的深度不超过 \\(u\\) 的深度的结点,由于我们是按从浅到深的顺序,所以一定已经被表出,代入即可。

由于叶子结点不超过 \\(n\\) 个,所以剖出链的个数 \\(O(n)\\),未知数个数 \\(O(n)\\),总时间复杂度 \\(O(n^3+n^2mk+|R|)\\),可以通过。


此外这题还可以使用概率生成函数。

不熟悉概率生成函数的同学可以先做做 歌唱王国硬币游戏

首先把输入的 \\(T_1,T_2,\\cdots,T_n\\) 拿去去重。

先考虑 \\(S\\) 初始为空的情况怎么做。

\\(F_i(x)=\\sum_{j\\ge 0} f_{i,j}x^j,G(x)=\\sum_{j\\ge 0} g_jx^j\\),其中 \\(f_{i,j}\\) 表示随机第 \\(j\\) 次时恰好跟 \\(T_i\\) 匹配上的概率,\\(g_j\\) 表示随机第 \\(j\\) 次时还没有结束的概率。

根据概率生成函数的基础知识,我们要求的是 \\((\\sum F_i)\'(1)\\)

由于 \\(g_{j-1}-g_{j}=\\sum_i f_{i,j}\\),于是有 \\(1+xG(x)=G(x)+\\sum_i F_i(x)\\)

此外我们根据 \\(n\\) 个串的信息还能列出 \\(n\\) 个方程。具体来说,若当前还没有结束随机过程,这时我们在串尾接上 \\(T_i=T_{i,1}T_{i,2}\\cdots T_{i,m}\\) 后,随机过程必然是已经结束了。然而也可能还没有接完 \\(T_i\\) 就已经匹配完了。总之:\\(G(x)\\prod_{k=1}^m(p_{T_{i,k}}x)=\\sum_{j=1}^n F_j(x)\\sum_{l|T_i[1:l]=T_j[m-l+1:m]}\\prod_{k=l+1}^m(p_{T_{i,k}}x)\\)

我们最终要求 \\((\\sum F_i)\'(1)\\)。由第一个式子:

\\((\\sum F_i)(x)=1+(x-1)G(x)\\)

\\((\\sum F_i)\'(x)=G(x)+(x-1)G\'(x)\\)

\\((\\sum F_i)\'(1)=G(1)\\)

所以我们求的其实就是 \\(G(1)\\)

由后面的式子,\\(G(1)\\prod_{k=1}^mp_{T_{i,k}}=\\sum_{j=1}^n F_j(1)\\sum_{l|T_i[1:l]=T_j[m-l+1:m]}\\prod_{k=m-l+1}^mp_{T_{j,k}}\\)

此外还有 \\(\\sum_{j=1}^n F_j(1)=1\\)

\\(n+1\\) 个方程 \\(n+1\\) 个未知数,可以解了。最后代入即得 \\(G(1)\\)

接下来是 \\(S\\) 初始不为空的情况,也就是我们给它钦定了一些前缀。

首先如果钦定的前缀里就包含了某个 \\(T_i\\),那就不用做了。

否则考虑照样列方程。第一个方程是不变的。

第二个方程如何改变呢?关键在于,刚刚列方程时在串尾接上 \\(T_i\\) 的操作是在哪里都可以做的,如果使用原来的方程就变成了只有开始随机之后才能接上。实际上还没开始随机的时候也可以往后面加 \\(T_i\\),而这样对原函数方程的贡献形如 \\(\\sum_{k}q_kx^k\\)(除 \\(x\\) 以外都是常数),而代入 \\(1\\) 以后就彻彻底底变成常数了。

因此每次只有常数项有改变,不用每次都高斯消元,只要矩阵求逆后乘向量即可。

时间复杂度 \\(O(n^3+n^2m+nmk+|R|)\\)

以上是关于The 2020 ICPC Asia Macau Regional Contest B Boring Problem的主要内容,如果未能解决你的问题,请参考以下文章

2020 ICPC Macau A. Accelerator(期望,计数,分治FFT)(每日一题 21.7.6)

The 2019 ICPC Asia Shanghai Regional Contest

The 2019 ICPC Asia Shanghai Regional Contest

The Preliminary Contest for ICPC Asia Yinchuan 2019

ACM-ICPC 2017 Asia Urumqi G. The Mountain

The 2018 ACM-ICPC Asia Qingdao Regional Contest, Online