【笔记】子序列问题

对于序列 a(n),我们称 b(m)a 的子序列,当且仅当存在 c(m) 使得 1i<m,ci<ci+1 并且 1im,aci=bi

一个序列的子序列有 2n 种,非空子序列有 2n1 种。

子序列的子序列有 3n​ 种,子序列的子序列的子序列有 4n 种,依次类推。

[Ynoi2015] 盼君勿忘#

每次询问一个序列所有子序列去重后的权值和之和。

考虑对每个权值算贡献,即有多少个子序列包含这个权值,简单容斥下就是 2n2cnt 个,所以贡献就是 (2n2cnt)x

例题#

给定一个子序列,求有多少个本质不同子序列。

定义 fi​ 表示以 i​ 结尾的本质不同子序列数,显然有 fi=fj​,其中 sj​ 是在 i​ 前面第一次出现。直接转移可以做到 O(|S|)​。

事实上我们有更优的容斥方法,定义状态 fi 表示前 i 个位置有多少个本质不同的子序列数。

考虑从 fifi+1,显然第 i+1 位可选可不选,所以 fi+1=2×fifprei+11,其中 prei 表示 i 前面第一个和 Si 相同的位置。时间复杂度为 O(|S|)

【模板】子序列自动机#

子序列自动机相对于子序列,好比后缀自动机相对与字符串,回文自动机相对与回文串。

我们观察例题的两种方法,找到二者的本质相同之处。

不难发现如果我们对于所有 i<j 使得 sj 是在 i 之后第一次出现,连一条 ij 的边,那么我们就会得到一个有向无环图,即子序列自动机。

所以自动机中的一条路径与一个子序列一一对应,本质不同的子序列数就是路径数。

对于例题的第一种方法,fi​​ 表示以 i 为终点了路径数,对于第二种方法表示前 i 个点的路径数,这样就很清晰是正确的。

例2 Distinct Subsequences#

求所有子序列的本质不同子序列个数之和。

显然就是求所有子序列的子序列自动机中路径条数。

所以我们可以定义状态 fi 表示以 i 结尾的所有子序列中,所有以 i 结尾的路径之和,那么 i 之后任意选,答案为 2nifi

我们枚举 j​ 进行转移,其中区间 [j+1,i1]​ 中等于 si​ 的位置不能选,其余位置任选,所以 fi=fj2cntjcntj 表示区间 [j+1,i1] 中不等于 si 的位置。

直接转移可以做到 O(n2),事实上我们发现在从小到大枚举 i 的过程中,对于 i 后面的 =si​ 的位置,相当于统一 /2,打个标记即可。这样就可以做到线性。

作者:7KByte

出处:https://www.cnblogs.com/7KByte/p/15359993.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   7KByte  阅读(257)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示