1. 动态规划解决子序列问题的核心思路
动态规划是解决子序列类问题的利器,其核心在于将问题分解为子问题,并通过状态转移方程建立子问题之间的联系。在解决字符串匹配、子序列查找等问题时,动态规划能够有效降低时间复杂度。
1.1 状态定义与初始化
对于字符串相关的动态规划问题,通常使用二维DP数组来记录状态。以最长公共子序列(LCS)为例:
dp[i][j]表示text1前i个字符和text2前j个字符的最长公共子序列长度- 边界条件:当
i=0或j=0时,dp[0][j] = 0和dp[i][0] = 0,因为空字符串与任何字符串的LCS长度都是0
在实际编码中,我们通常会使用
dp[text1.length()+1][text2.length()+1]的数组大小,并将dp[0][j]和dp[i][0]初始化为0,这样可以简化边界条件的处理。
1.2 状态转移方程的构建
状态转移方程是动态规划的核心,对于子序列问题,通常有两种情况:
- 当前字符匹配时:
java复制if(text1.charAt(i-1) == text2.charAt(j-1)) {
dp[i][j] = dp[i-1][j-1] + 1;
}
- 当前字符不匹配时:
java复制else {
dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
}
这种设计允许我们在字符不匹配时"跳过"其中一个字符,这正是子序列与子数组问题的关键区别。子序列可以不连续,而子数组必须连续。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 最长公共子序列(LCS)的深入解析
2.1 问题描述与示例分析
给定两个字符串 text1 和 text2,返回它们的最长公共子序列的长度。子序列是指通过删除某些字符而不改变剩余字符相对顺序得到的新字符串。
示例分析:
- text1 = "abcde", text2 = "ace" → LCS是"ace",长度为3
- text1 = "abc", text2 = "def" → 没有公共子序列,返回0
2.2 完整实现与优化
基础实现:
java复制publi
