一直鸽着这个东西,现在回来学一下。
子序列自动机
P5826 【模板】子序列自动机/P3500 [POI2010]TES-Intelligence Test
我们考虑怎么在某个序列 \(a\) 上匹配一个序列 \(b\),在匹配字符 \(c\) 时只需要每次贪心找到当前匹配位置后面最近的 \(c\) 即可,这启发我们设计自动机模型。
字符集为原序列的字符集。
状态集合为位置 \(0,1,2,\cdots,n\),以及垃圾站 \(n+1\)。
起始状态为位置 \(1\)。
接受状态集合为除了 \(n+1\) 外的位置。
转移函数为
\[\delta(x,c)=\{i\mid i>x,a_i=c\}
\]
那么我们只需要从后往前扫一遍就可以得到转移函数了。
由于字符集过大,所以不能存下所有转移函数,所以需要采用可持久线段树,复杂度 \(O((|S|+\sum|T|)\log |S|)\)。
更快的离线算法
上面的做法适用面更广,但是如果我们允许离线,是否存在更优秀的算法呢?
实际上,我们只需要把询问挂在它的第一个值上面,然后把序列从前往后扫一遍,每次把当前值对应的询问转移到下一个值就可以了。
这样的复杂度是 \(O(|S|+\sum|T|+|\Sigma|)\)。
例题
例题1 P4112 [HEOI2015]最短不公共子串
子序列自动机最知名,最经典的例题。
考虑建出两个串的 SAM 以及子序列自动机。
观察数据范围支持平方,我们可以每次直接在两个自动机上 bfs 求解,那么一个状态对只会遍历一次,复杂度 \(O(n^2|\Sigma|)\)。
例题2 P4584 [FJOI2015]带子串包含约束LCS问题
不是很有意思的题,至少帮我复习了一下 tuple。
首先对约束串建出 ACAM,对两个询问串建出子序列自动机,状压一手匹配的串数量,然后直接类似 SPFA 求最长路就好了。
复杂度是玄学。
例题3 P3728 曼哈顿序列
跟 P3975 [TJOI2015]弦论 差不多。
直接 dp 一下然后再直接搜一手就好了。
例题4 P4608 [FJOI2016]所有公共子序列问题
sb 题啊。
跟上一题类似的 dp,要写高精度,cls。