一、子序列的本质
子序列是从原字符串中选择任意数量的字符(可以是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 开始遍历。
四、如何将二进制数转换为子序列?
外层循环遍历所有可能的二进制数:
对于
n=3,遍历1(001)到7(111)。
内层循环检查每一位是否为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)