⭐算法OJ⭐字符串与数组【动态规划DP】(C++实现)最长公共子序列LCS+最短公共超序列SCS
- 开源代码
- 2025-09-12 10:27:01

动态规划(Dynamic Programming, DP)在字符串数组相关的算法题中应用广泛,尤其是在解决子序列、子串、编辑距离、匹配等问题时。动态规划的核心思想是将问题分解为子问题,并通过存储子问题的解来避免重复计算,从而提高效率。
文章目录 1143. Longest Common Subsequence问题描述解题思路C++ 实现 1092. Shortest Common Supersequence解题思路C++ 实现 1143. Longest Common SubsequenceGiven two strings text1 and text2, return the length of their longest common subsequence. If there is no common subsequence, return 0.
A subsequence of a string is a new string generated from the original string with some characters (can be none) deleted without changing the relative order of the remaining characters.
For example, "ace" is a subsequence of "abcde". A common subsequence of two strings is a subsequence that is common to both strings.
Example 1:
Input: text1 = "abcde", text2 = "ace" Output: 3 Explanation: The longest common subsequence is "ace" and its length is 3.Example 2:
Input: text1 = "abc", text2 = "abc" Output: 3 Explanation: The longest common subsequence is "abc" and its length is 3.Example 3:
Input: text1 = "abc", text2 = "def" Output: 0 Explanation: There is no such common subsequence, so the result is 0. 问题描述给定两个字符串 s1 和 s2,找到它们的最长公共子序列的长度。子序列是指从原字符串中删除一些字符(可以不连续)后得到的新字符串。
解题思路 定义状态:dp[i][j] 表示 s1 的前 i 个字符和 s2 的前 j 个字符的最长公共子序列长度。状态转移: 如果 s1[i-1] == s2[j-1],则 dp[i][j] = dp[i-1][j-1] + 1。否则,dp[i][j] = max(dp[i-1][j], dp[i][j-1])。 初始化:dp[0][j] = 0 和 dp[i][0] = 0,表示空字符串的 LCS 长度为 0。结果:dp[m][n],其中 m 和 n 分别是 s1 和 s2 的长度。 C++ 实现 int longestCommonSubsequence(string s1, string s2) { int m = s1.length(), n = s2.length(); vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0)); for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { if (s1[i - 1] == s2[j - 1]) { dp[i][j] = dp[i - 1][j - 1] + 1; } else { dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); } } } return dp[m][n]; } 1092. Shortest Common SupersequenceGiven two strings str1 and str2, return the shortest string that has both str1 and str2 as subsequences. If there are multiple valid strings, return any of them.
A string s is a subsequence of string t if deleting some number of characters from t (possibly 0) results in the string s.
Example 1:
Input: str1 = "abac", str2 = "cab" Output: "cabac" Explanation: str1 = "abac" is a subsequence of "cabac" because we can delete the first "c". str2 = "cab" is a subsequence of "cabac" because we can delete the last "ac". The answer provided is the shortest such string that satisfies these properties.Example 2:
Input: str1 = "aaaaaaaa", str2 = "aaaaaaaa" Output: "aaaaaaaa" 解题思路这个问题可以转化为求两个字符串的最长公共子序列(LCS),然后通过 LCS 构造最短的公共超序列。
构造最短公共超序列
初始化指针: 使用指针 i 和 j 分别遍历 str1 和 str2。 遍历字符串: 如果 str1[i] == str2[j],则将当前字符添加到结果中,并移动两个指针。否则,将 str1[i] 或 str2[j] 中较小的字符添加到结果中,并移动对应的指针。 处理剩余字符: 如果 str1 或 str2 有剩余字符,将它们全部添加到结果中。 C++ 实现 string shortestCommonSupersequence(string str1, string str2) { int m = str1.length(), n = str2.length(); // 动态规划求 LCS vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0)); for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { if (str1[i - 1] == str2[j - 1]) { dp[i][j] = dp[i - 1][j - 1] + 1; } else { dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); } } } // 构造最短公共超序列 string result; int i = m, j = n; while (i > 0 && j > 0) { if (str1[i - 1] == str2[j - 1]) { result.push_back(str1[i - 1]); i--; j--; } else if (dp[i - 1][j] > dp[i][j - 1]) { result.push_back(str1[i - 1]); i--; } else { result.push_back(str2[j - 1]); j--; } } // 处理剩余字符 while (i > 0) { result.push_back(str1[i - 1]); i--; } while (j > 0) { result.push_back(str2[j - 1]); j--; } // 反转结果 reverse(result.begin(), result.end()); return result; }⭐算法OJ⭐字符串与数组【动态规划DP】(C++实现)最长公共子序列LCS+最短公共超序列SCS由讯客互联开源代码栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“⭐算法OJ⭐字符串与数组【动态规划DP】(C++实现)最长公共子序列LCS+最短公共超序列SCS”