最长公共子序列的变种:带字符出现次数限制的最长公共子序列(进阶版:限制某些字符必须连续出现k次)
字数 1196 2025-11-09 10:55:00
最长公共子序列的变种:带字符出现次数限制的最长公共子序列(进阶版:限制某些字符必须连续出现k次)
题目描述:
给定两个字符串s和t,以及一个字符c和整数k。要求找到s和t的最长公共子序列,且该子序列中字符c必须连续出现至少k次。如果不存在这样的子序列,返回0。
解题过程:
这个问题是LCS的变种,增加了对特定字符连续出现次数的限制。我们需要在动态规划状态中额外记录关于字符c连续出现次数的信息。
- 状态定义:
定义dp[i][j][x][y],其中:
- i: 在s中处理到第i个字符(1-indexed)
- j: 在t中处理到第j个字符(1-indexed)
- x: 当前公共子序列末尾字符c的连续出现次数(0表示当前字符不是c)
- y: 表示当前是否已经开始c的连续序列(0未开始,1已开始)
- 状态转移:
考虑四种情况:
情况1:不选择s[i]和t[j]
dp[i][j][x][y] = max(dp[i][j][x][y], dp[i-1][j-1][x][y])
情况2:选择s[i]和t[j],且s[i] == t[j]
- 如果s[i] == c:
- 如果x > 0(前一个字符也是c):dp[i][j][x+1][1] = max(dp[i][j][x+1][1], dp[i-1][j-1][x][y] + 1)
- 如果x == 0(前一个字符不是c):dp[i][j][1][1] = max(dp[i][j][1][1], dp[i-1][j-1][x][y] + 1)
- 如果s[i] != c:
dp[i][j][0][y] = max(dp[i][j][0][y], dp[i-1][j-1][x][y] + 1)
情况3:不选择s[i],选择t[j]
dp[i][j][x][y] = max(dp[i][j][x][y], dp[i-1][j][x][y])
情况4:选择s[i],不选择t[j]
dp[i][j][x][y] = max(dp[i][j][x][y], dp[i][j-1][x][y])
- 初始化:
- dp[0][0][0][0] = 0
- 其他位置初始化为负无穷(表示不可达状态)
-
结果提取:
最终结果是所有满足x >= k的dp[n][m][x][1]中的最大值(n和m分别是s和t的长度) -
优化:
由于状态空间较大,可以考虑使用滚动数组优化空间复杂度。
这个算法的时间复杂度是O(n×m×k),其中n和m是字符串长度,k是要求的连续出现次数。通过记录字符c的连续出现情况,我们能够在寻找LCS的同时满足对特定字符连续出现次数的限制要求。