一、子序列的本质
子序列是从原字符串中选择任意数量的字符(可以是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)