📌  相关文章
📜  给定二进制字符串可被 2 整除的子序列数(1)

📅  最后修改于: 2023-12-03 15:41:16.451000             🧑  作者: Mango

给定二进制字符串可被 2 整除的子序列数

问题描述

给定一个由 0 和 1 组成的二进制字符串 s,求出其中总共有多少个不同的子序列,满足其所代表的二进制数可以被 2 整除。

解题思路

对于任意的二进制数,其末位只有 0 或 1 两种可能,而被 2 整除的二进制数,其末位必须是 0,因此,对于给定的二进制字符串 s,我们可以把所有末位为 0 的子序列都找出来,这些子序列所代表的二进制数均可以被 2 整除。

对于一个长度为 n 的二进制字符串 s,定义 f(i,j) 表示从 i 到 j 这段子串的不同的子序列中,能够被 2 整除的子序列数。则我们有以下状态转移方程:

  • 当 s[j] = 0 时,f(i,j) = f(i,j-1) + f(i,j-1),即包含 s[j] 和不包含 s[j] 两种情况
  • 当 s[j] = 1 时,f(i,j) = f(i,j-1),因为末位为 1 的子序列不可能被 2 整除

最终,可被 2 整除的子序列数为 f(0,n-1)。

代码示例
def countSubsequences(s: str) -> int:
    n = len(s)
    dp = [[0] * n for _ in range(n)]

    # 初始化
    for i in range(n):
        if s[i] == '0':
            dp[i][i] = 1

    # 状态转移
    for i in range(n):
        for j in range(i+1, n):
            if s[j] == '1':
                dp[i][j] = dp[i][j-1]
            else:
                dp[i][j] = dp[i][j-1] + dp[i][j-1]

    return dp[0][n-1]

该算法的时间复杂度为 $O(n^2)$,空间复杂度为 $O(n^2)$。