【区间dp】lc730及其扩展问题题解

传送门

lc730题解

又💧一篇

作者:hans774882968以及hans774882968

原问题要求去重,增加了分析的难度。若去掉该要求,则可以直接基于容斥原理来得到转移方程。仍然采用定义:dp[L][R]s[L~R]中的回文子序列个数。仍然分s[L] == s[R]和不相等来讨论。

  • 不相等,则两端无法同时参与构建回文子序列,仍然根据容斥原理,得dp[L][R] = dp[L + 1][R] + dp[L][R - 1] - dp[L + 1][R - 1]
  • 相等,则在容斥原理式子的基础上加上两端同时参与的方案数。对于t ∈ dp[L+1][R-1],加上两端的字符ch,都合法。再加上ch + ch,故为dp[L][R] = dp[L + 1][R] + dp[L][R - 1] + 1
class Solution:
    def bf(self, s: str) -> int:
        n = len(s)
        ans = 0
        for S in range(1, 1 << n):
            t = ""
            for i in range(n):
                if S >> i & 1:
                    t += s[i]
            if t == t[::-1]:
                ans += 1
        return ans

    def countPalindromicSubsequences(self, s: str) -> int:
        n, C, mod = len(s), 4, int(1e9) + 7
        dp = [[0] * n for _ in range(n)]
        for i in range(n):
            dp[i][i] = 1
        for L in range(n - 1, -1, -1):
            for R in range(L + 1, n):
                if s[L] == s[R]:
                    dp[L][R] = (dp[L + 1][R] + dp[L][R - 1] + 1) % mod
                else:
                    dp[L][R] = ((dp[L + 1][R] + dp[L][R - 1] -
                                dp[L + 1][R - 1]) % mod + mod) % mod
        if n <= 20:
            assert dp[0][n - 1] == self.bf(s)
        return dp[0][n - 1]


def test1(s):
    for i in range(1, 8):
        for it in itertools.product(*(['abcd'] * i)):
            v = "".join(it)
            s.countPalindromicSubsequences(v)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值