题意简述
给个串 $s$,求有多少个长为 $m$ 的串,无限次重复后能找到一个长为 $|s|$ 的字典序小于 $s$ 的子串。
小写字母,$|s|, m\le 2000$。
主要思路
设 $n = |s|$ 与 $m$ 同阶。看到 rqy 的题解搞了一个 $O(n\operatorname{poly}(n))$ 的做法,然后我比较菜没看懂,于是采用了比较多人用的 kmp 做法。
首先给 $s$ 建 kmp 自动机,考虑把一个串 $t$ 扔到上面跑,判断是否合法。
发现加入一个字符 $c$ 时,如果当前位置的 fail 树上的祖先存在一个点的下一个位置大于 $c$,直接返回合法。
所以考虑统计不合法串的个数。
此时自动机变成这样:对于每个点,存在一个字符 $c$,使得下一个字符是 $c$ 时会指向某个位置,大于 $c$ 时会指向原点,小于 $c$ 时则转移不存在。
考虑一个不合法串 $t$,若其重复足够多次后在自动机上匹配到状态 $pos$,那么走 $m$ 步仍然会回到 $pos$。
于是可以求出 $dp(i, j)$ 表示从原点走 $i$ 步走到 $j$ 的方案数,然后枚举位置 $pos$,枚举走了几步才第一次走到原点,然后用 dp 数组计算答案。
复杂度 $O(nm)$。
这种东西场上我一辈子都想不出来罢
参考代码
细节见代码。
1 |
|