子序列dp问题

问题:给出一个长度为 n ( 1 ≤ n ≤ 1 0 6 ) n \quad(1 \leq n \leq 10^{6}) n(1n106)的字符串,你需要求出该字符串有多少个不同的子序列。

子序列的问题乍一看和字串的问题很相似,可能要用到后缀数组等高级数据结构。仔细想想其实没有必要的,一个 O ( n ) O(n) O(n) d p dp dp就可以解决。

对于给出的字符串 A [ 1 ] , A [ 2 ] , . . . A [ n ] A[1],A[2],...A[n] A[1],A[2],...A[n],我们用 d p [ i ] dp[i] dp[i]表示以字符 A [ i ] A[i] A[i]结尾的子序列的数量,显然这个 d p dp dp的关键点在于如何不重不漏的计算答案(其实这也是很多 d p dp dp方程需要想的问题)。

在考虑 d p [ i ] dp[i] dp[i]时,显然我们要尝试把字符 A [ i ] A[i] A[i]接到前面已经构成的子序列后面,那是不是 d p [ i ] = ∑ j = 0 i − 1 d p [ j ] dp[i]=\sum_{j=0}^{i-1}dp[j] dp[i]=j=0i1dp[j]?不完全正确。

我们发现 当存在一个字符 A [ j ] = A [ i ] ( 1 ≤ j ≤ i − 1 ) A[j]=A[i]\quad (1\leq j \leq i-1) A[j]=A[i](1ji1)时,将 A [ i ] A[i] A[i]接到 j j j以前的子序列构成的字符串和将 A [ j ] A[j] A[j]接到 j j j以前的子序列构成的字符串相同。

因此我们可以记录每一个字符出现的上一个位置,在转移过程中,只计算到这个位置就可以了,当然我们要初始化 d p [ 0 ] = 1 dp[0]=1 dp[0]=1

A [ i ] A[i] A[i]出现的上一个位置是 l a s las las,即 A [ i ] = A [ l a s ] A[i]=A[las] A[i]=A[las]。开始 d p dp dp前所有的 l a s las las都是 0 0 0,表示这个字符上次出现的位置是 0 0 0

那么 正确的 d p dp dp方程就是 d p [ i ] = ∑ j = l a s j = i − 1 d p [ j ] dp[i]=\sum_{j=las}^{j=i-1}dp[j] dp[i]=j=lasj=i1dp[j]

最终的答案: a n s = ∑ j = 1 j = n d p [ j ] ans=\sum_{j=1}^{j=n}dp[j] ans=j=1j=ndp[j]

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值