利用自动机模型处理动态规划的转移路径
这个套路俗称 dp 套 dp。
大致思路就是把 dp 的转移路径用一个自动机模型处理出来。
自动机它本身只是一个定义,这里并不怎么利用它的性质。只是因为这种根据一个字符从一个结点转移到另一个结点,和某些动态规划的转移很相似而已。
众所周知有 KMP、ACM、SAM 套 dp 的套路。而对于一些性质没有这么好的问题,就得自己设计一个并不那么高效的自动机,去规划 dp 的转移路径。
有时可以处理一些非常诡异的计数 dp。
一句话概括:把同一层、转移路径相同的状态,压成自动机上的一个结点。
\(\texttt{TJOI2018 }\text{游园会}\)
字符集 \(\Sigma=\{N,O,I\}\)。给定模板串 \(T\),分别对于每个 \(p=0,1,\cdots,\left|T\right|\),求出满足如下条件的字符串 \(S\) 数量:
- 长度为 \(n\)。
- 不存在 \(NOI\) 为它的子串。
- \(\left|LCS(S,T)\right|=p\)(Longest Common Substring)。
设计状态 \(dp_{i,j,u}\) 用来计数。其中这里的 \(u\) 主要是用于自动机上的转移,可以看成自动机上的编号,希望把转移路径相同的 \(S\) 放到这上面。\(i,j\) 的定义是套路的,\(i\) 代表考虑大小为 \(i\) 的串,\(j\) 用来避免出现 \(NOI\) 子串。
如果枚举第 \(i\) 位的字符 \(S_i\),由于 LCS 的转移为
因此自动机结点 \(u\) 上应该维护的信息是:对于所有 \(t=0,1,\cdots,\left|T\right|\),\(lcs_{t}\)(因为这个 \(i\) 是自动机结点的深度,所以把 \(i\) 省略掉了) 是多少。注意到给了 \(S_i\) 后,就可以从深度为 \(i-1\) 的自动机结点 \(u\) 确定唯一的深度为 \(i\) 的自动机结点 \(v\),计数就是一个直接的累加。
这样,就完成了一个路径规划。
现在来考虑结点数量。注意到一个自动机结点 \(v\) 的 \(lcs\) 数组的转移
因此 \(lcs\) 数组单调不减。继续观察,可以证明,\(0\le lcs_{t}-lcs_{t-1}\le 1\)。因此根据差分数组,这样的数组最多有 \(2^{\left|T\right|}\) 个。因此,自动机每层都只有 \(O(2^{\left|T\right|})\) 个有用的结点。
最后的统计是容易的。总复杂度可以做到 \(O(2^{\left|T\right|}(n+\left|T\right|))\)。
\(\square\)
\(\texttt{ZJOI2019 }\text{麻将}\)
\(n\ge 5\) 种不同的麻将,编号依次为 \(1,2,\cdots,n\),每种有 \(4\) 张。
一个形如 \((i,i+1,i+2)\) 或 \((i,i,i)\) 的三元组被称为面子。
一个形如 \((i,i)\) 的二元组被称为对子。
一个麻将集合 \(S\) 是胡的,当且仅当它满足以下两个条件中至少一个
- 可以划分成 \(4\) 个面子和 \(1\) 个对子(\(14=4\times 3+1\times 2\))。
- 可以划分成 \(7\) 个对子(\(14=7\times 2\))。
先给 \(13\) 张麻将。剩下的麻将随机打乱,每次随便摸一张 不放回去,直到手里的麻将集合存在一个子集是胡的。求期望拿几张才能胡。
用每种排列用了多少次恰好胡了除以总排列数量,主要考虑这些次数的和。
比较经典地枚举次数,看看这个第几次取完还有多少种情况没胡(和 \(\texttt{NOIP2020 }\text{微信步数}\) 类似),这个看起来会比较容易 dp。记第 \(i\) 次还没胡的情况数量为 \(f_i\),这样,答案就是
后面我懒得想,先咕咕咕了。

浙公网安备 33010602011771号