最长公共子序列的变种:带字符必须按顺序出现限制的最长公共子序列(进阶版:限制某些字符必须连续出现k次)
字数 1244 2025-11-21 00:42:00
最长公共子序列的变种:带字符必须按顺序出现限制的最长公共子序列(进阶版:限制某些字符必须连续出现k次)
题目描述
给定两个字符串s和t,以及一个字符集合C和一个整数k。要求找到s和t的最长公共子序列,且满足:
- 对于集合C中的每个字符,如果在子序列中出现,则必须连续出现至少k次
- 子序列中C集合字符的连续出现段必须完整(不能截断)
例如:
s = "abcde", t = "ace", C = {'c'}, k = 1
最长公共子序列为 "ace",其中'c'连续出现1次,满足条件。
解题思路
步骤1:理解问题本质
这是一个带限制条件的最长公共子序列(LCS)问题。我们需要在标准的LCS动态规划基础上,增加对特定字符连续出现次数的限制。
步骤2:状态定义
定义dp[i][j][x]表示:
- 考虑s的前i个字符和t的前j个字符
- 当前正在构建的C集合字符的连续出现长度为x
- 的值表示当前最长公共子序列长度
但这样定义状态空间太大,更好的方法是:
定义dp[i][j]表示考虑s的前i个字符和t的前j个字符时的最长公共子序列长度
定义cnt[i][j]表示在达到dp[i][j]时,当前C集合字符的连续出现长度
步骤3:状态转移方程
对于每个位置(i, j):
-
如果s[i-1] == t[j-1](字符匹配):
- 如果当前字符 ∈ C:
- 如果前一个状态cnt[i-1][j-1] >= k-1 或者 前一个字符不在C中:
dp[i][j] = dp[i-1][j-1] + 1
cnt[i][j] = cnt[i-1][j-1] + 1 - 否则:
跳过这个匹配(因为不满足连续k次的限制)
- 如果前一个状态cnt[i-1][j-1] >= k-1 或者 前一个字符不在C中:
- 如果当前字符 ∉ C:
dp[i][j] = dp[i-1][j-1] + 1
cnt[i][j] = 0(重置计数器)
- 如果当前字符 ∈ C:
-
如果s[i-1] != t[j-1](字符不匹配):
dp[i][j] = max(dp[i-1][j], dp[i][j-1])
选择cnt值时,要选择与dp值对应的cnt值
步骤4:初始化
- dp[0][j] = 0, cnt[0][j] = 0(空字符串)
- dp[i][0] = 0, cnt[i][0] = 0(空字符串)
步骤5:算法实现
def longestCommonSubsequenceWithConstraint(s, t, C, k):
m, n = len(s), len(t)
dp = [[0] * (n + 1) for _ in range(m + 1)]
cnt = [[0] * (n + 1) for _ in range(m + 1)]
for i in range(1, m + 1):
for j in range(1, n + 1):
if s[i-1] == t[j-1]:
if s[i-1] in C:
# 检查是否满足连续k次的限制
if cnt[i-1][j-1] >= k - 1 or (i-1 == 0 or j-1 == 0 or s[i-2] not in C):
dp[i][j] = dp[i-1][j-1] + 1
cnt[i][j] = cnt[i-1][j-1] + 1
else:
# 不满足限制,跳过这个匹配
dp[i][j] = max(dp[i-1][j], dp[i][j-1])
cnt[i][j] = cnt[i-1][j-1] # 保持原计数
else:
# 普通字符,正常处理
dp[i][j] = dp[i-1][j-1] + 1
cnt[i][j] = 0 # 重置计数器
else:
# 字符不匹配,选择较大的那个
if dp[i-1][j] > dp[i][j-1]:
dp[i][j] = dp[i-1][j]
cnt[i][j] = cnt[i-1][j]
else:
dp[i][j] = dp[i][j-1]
cnt[i][j] = cnt[i][j-1]
return dp[m][n]
步骤6:复杂度分析
- 时间复杂度:O(m × n),其中m和n分别是两个字符串的长度
- 空间复杂度:O(m × n),用于存储dp和cnt数组
示例验证
例1:s = "abcde", t = "ace", C = {'c'}, k = 1
结果:3(子序列"ace")
例2:s = "aabcc", t = "aacc", C = {'c'}, k = 2
结果:4(子序列"aacc",其中'c'连续出现2次)
这个算法在标准LCS的基础上,通过额外的计数数组来跟踪特定字符的连续出现情况,确保满足题目中的限制条件。