当前位置: 首页 > news >正文

⭐算法OJ⭐字符串与数组【动态规划 DP】(C++实现)最长公共子序列 LCS + 最短公共超序列 SCS

动态规划(Dynamic Programming, DP)在字符串数组相关的算法题中应用广泛,尤其是在解决子序列、子串、编辑距离、匹配等问题时。动态规划的核心思想是将问题分解为子问题,并通过存储子问题的解来避免重复计算,从而提高效率。

文章目录

  • 1143. Longest Common Subsequence
    • 问题描述
    • 解题思路
    • C++ 实现
  • 1092. Shortest Common Supersequence
    • 解题思路
    • C++ 实现

1143. Longest Common Subsequence

Given 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.

问题描述

给定两个字符串 s1s2,找到它们的最长公共子序列的长度。子序列是指从原字符串中删除一些字符(可以不连续)后得到的新字符串。

解题思路

  • 定义状态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] = 0dp[i][0] = 0,表示空字符串的 LCS 长度为 0。
  • 结果dp[m][n],其中 mn 分别是 s1s2 的长度。

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 Supersequence

Given 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 构造最短的公共超序列。

构造最短公共超序列

  • 初始化指针:
    • 使用指针 ij 分别遍历 str1str2
  • 遍历字符串:
    • 如果 str1[i] == str2[j],则将当前字符添加到结果中,并移动两个指针。
    • 否则,将 str1[i]str2[j] 中较小的字符添加到结果中,并移动对应的指针。
  • 处理剩余字符:
    • 如果 str1str2 有剩余字符,将它们全部添加到结果中。

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;
}

相关文章:

  • 洛谷 P11830 省选联考2025 幸运数字 题解
  • 【编程题】7-3 树的同构
  • VS Code(Cursor)远程开发调试教程(超详细)
  • 自己的网页加一个搜索框,调用deepseek的API
  • 深入理解UDP:一种高效但不可靠的传输层协议、揭示其工作原理
  • 《2025软件测试工程师面试》接口测试篇
  • spark 常见操作命令
  • leetcode 148. 排序链表
  • 交叉编译 perl-5.40.0 perl-cross-1.5.3
  • 记浙江大华校招Java面试
  • Linux基础开发工具(vim编译器,yum与apt软件安装)
  • 计算机基础面试(操作系统)
  • Angular Superresolution with Antenna Pattern Errors论文阅读
  • 《数字图像处理》第一章绪论笔记:从“一图胜千言”到技术基石
  • C++-第十八章:线程相关内容
  • 如何用 TikTok 的创作工具提升你的视频质量?
  • Magic 1-For-1: 在一分钟内生成一分钟视频片段(基于Python实现,视频生成模型)
  • SpringBoot 多环境配置
  • leetcode141.环形链表,142环形链表ii
  • C++理解(六)
  • 网站更新要怎么做/推广接单平台
  • 总部基地网站建设/seo综合查询工具
  • 一家专门做原产地的网站/郑州做网站公司排名
  • 烟台做网站那家好/免费建站的网站哪个好
  • 做系统的图标下载网站/页面优化算法
  • 手机免费代理ip网站/巩义网络推广