一、子序列的本质

子序列是从原字符串中选择任意数量的字符(可以是0个、1个、...、所有字符),且保持这些字符的原始顺序形成的字符串。例如:原字符串 "abc" 的子序列包括 "a", "b", "c", "ab", "ac", "bc", "abc" 和空字符串 ""(共 2^3=8 种可能性)。

二、位掩码(Bitmask)的引入

假设字符串长度为 n,我们可以用一个 n 位的二进制数 来表示是否选择某个字符:

  • 二进制数的每一位对应原字符串的一个字符。

  • 如果某一位是 1,表示选择对应的字符;如果是 0,表示不选择。

例如,对于字符串 "abc"(n=3):

  • 二进制数 101(十进制5)表示选择第1个字符 "a" 和第3个字符 "c",生成子序列 "ac"

  • 二进制数 010(十进制2)表示选择第2个字符 "b",生成子序列 "b"

三、遍历所有可能的二进制数

所有可能的二进制数范围是 0(全0)到 2^n - 1(全1)。例如,n=3时:

  • 范围是 000(0)到 111(7),共 2^3=8 种可能。

  • 每个二进制数对应一种子序列选择方式。

如果包含 000(0),对应空字符串 ""。若不需要空字符串,可以从 1 开始遍历。

四、如何将二进制数转换为子序列?

  1. 外层循环遍历所有可能的二进制数

    • 对于 n=3,遍历 1001)到 7111)。

  2. 内层循环检查每一位是否为1

    • 对于每个二进制数 mask,遍历其每一位 i(从0到n-1)。

    • 如果 mask 的第 i 位是1(即 mask & (1 << i) 为真),则将原字符串的第 i 个字符加入子序列。

五、代码示例

def get_all_subsequences(s):
    n = len(s)
    subsequences = set()
    for mask in range(1, 1 << n):  # 遍历1到2^n-1
        subseq = []
        for i in range(n):
            if mask & (1 << i):    # 检查第i位是否为1
                subseq.append(s[i])
        subsequences.add(''.join(subseq))
    return list(subsequences)

泥嚎~