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

【Leetcode】1092. Shortest Common Supersequence

题目地址:

https://leetcode.com/problems/shortest-common-supersequence/description/

给定两个字符串 s 1 s_1 s1 s 2 s_2 s2,求一个字符串 s s s,使得 s 1 s_1 s1 s 2 s_2 s2都是其子序列,并且要求 s s s尽可能短。

f [ i ] [ j ] f[i][j] f[i][j] s 1 s_1 s1添加多少个字符可以使得 s 2 s_2 s2为其子序列。设下标都从 1 1 1开始。初始条件 f [ 0 ] [ j ] = j f[0][j]=j f[0][j]=j
1、如果 s 1 [ i ] = s 2 [ j ] s_1[i]=s_2[j] s1[i]=s2[j],那么最后一个字母已经相等了,只需要让 s 1 s_1 s1前面添加若干字符即可,所以此时 f [ i ] [ j ] = f [ i − 1 ] [ j − 1 ] f[i][j]=f[i-1][j-1] f[i][j]=f[i1][j1]
2、如果 s 1 [ i ] ≠ s 2 [ j ] s_1[i]\ne s_2[j] s1[i]=s2[j],那么为了使得 s 1 s_1 s1 s 2 s_2 s2的母序列,必须首先要将 s 2 [ j ] s_2[j] s2[j]包含进去,那么有两种可能,第一种是只在 s 1 [ i ] s_1[i] s1[i]这个位置之前添加字符,此时 f [ i ] [ j ] = f [ i − 1 ] [ j ] f[i][j]=f[i-1][j] f[i][j]=f[i1][j];第二种是在 s 1 [ i ] s_1[i] s1[i]这个位置之后添加字符(之前也有可能添加),那么之后添加的最后一个字符必然等于 s 2 [ j ] s_2[j] s2[j],否则没必要添加,所以此时 f [ i ] [ j ] = f [ i ] [ j − 1 ] + 1 f[i][j]=f[i][j-1]+1 f[i][j]=f[i][j1]+1。综上 f [ i ] [ j ] = min ⁡ { f [ i − 1 ] [ j ] , f [ i ] [ j − 1 ] + 1 } f[i][j]=\min\{f[i-1][j],f[i][j-1]+1\} f[i][j]=min{f[i1][j],f[i][j1]+1}

具体方案可以倒着推,即从 i = m , j = n i=m,j=n i=m,j=n开始,如果 s 1 [ i ] = s 2 [ j ] s_1[i]=s_2[j] s1[i]=s2[j],那么最优方案就是 f [ i − 1 ] [ j − 1 ] f[i-1][j-1] f[i1][j1],只需要 s 1 [ i ] s_1[i] s1[i]这个字符;如果 s 1 [ i ] = s 2 [ j ] s_1[i]=s_2[j] s1[i]=s2[j]则需要分情况,如果 f [ i ] [ j ] = f [ i − 1 ] [ j ] f[i][j]=f[i-1][j] f[i][j]=f[i1][j],则最优方案是在 s 1 [ i ] s_1[i] s1[i]之前添加字符,需要将 s 1 [ i ] s_1[i] s1[i]加入答案;如果 f [ i ] [ j ] = f [ i ] [ j − 1 ] + 1 f[i][j]=f[i][j-1]+1 f[i][j]=f[i][j1]+1,则说明需要把 s 2 [ j ] s_2[j] s2[j]加入答案。当 i = 0 i=0 i=0的时候,要将 s 2 [ j ] s_2[j] s2[j]所有剩余字符都加入答案。最后将答案反序。代码如下:

class Solution {
 public:
  string shortestCommonSupersequence(string s1, string s2) {
    int m = s1.size(), n = s2.size();
    s1 = " " + s1;
    s2 = " " + s2;
    int f[m + 1][n + 1];
    memset(f, 0, sizeof f);
    for (int i = 0; i <= n; i++) f[0][i] = i;
    for (int i = 1; i <= m; i++)
      for (int j = 1; j <= n; j++) {
        if (s1[i] == s2[j]) f[i][j] = f[i - 1][j - 1];
        else f[i][j] = min(f[i - 1][j], f[i][j - 1] + 1);
      }
    
    string res;
    for (int i = m, j = n; i;) {
      if (s1[i] == s2[j]) {
        res.push_back(s2[j--]);
        i--;
      } else {
        if (f[i][j] == f[i - 1][j]) res.push_back(s1[i--]);
        else res.push_back(s2[j--]);
      }
      if (!i) while (j) res.push_back(s2[j--]);
    }
    reverse(res.begin(), res.end());
    return res;
  }
};

时空复杂度 O ( l s 1 l s 2 ) O(l_{s_1}l_{s_2}) O(ls1ls2)

相关文章:

  • 文本向量化模型新突破——acge_text_embedding勇夺C-MTEB榜首
  • 在 vue3 中使用高德地图
  • 美森快船和以星快船有什么区别?美线海运都有哪些快船?
  • 2-2 任务:闰年判断
  • 索引的最左匹配原则
  • vue 3 + TS 组合式标注类型
  • Android 验证启动模式
  • R 贝叶斯输出分析和诊断MCMC:coda包
  • Spring Boot到底是如何进行自动配置的?
  • SD-WAN技术:优化国内外服务器访问的关键
  • github新手用法详解
  • 亿道丨三防平板丨手持平板丨加固平板丨助力地震救援
  • Datawhale 202210 Excel | 第五、六、七章 Excel函数示例 Excel函数列表
  • matlab实时串口通讯示例
  • 18-CSS3的2D和3D属性
  • 【韩顺平老师讲MySQL】数据类型详解
  • 认识和了解Linux文件系统。
  • Simulink 自动代码生成电机控制:基于Keil软件集成
  • 【ArchSummit】小红书缓存服务多云建设之路
  • Educational Codeforces Round 137 (Rated for Div. 2)-赛后总结
  • Python图形处理
  • 【网站架构】4核CPU的MySQL调优3万RPS吞吐量?数据库集群高可用
  • Codeforces Round #828 (Div. 3)-赛后总结
  • C语言指针个人理解
  • 网络安全系统性学习路线「全文字详细介绍」
  • 你有一份奖学金,请注意查收~浙江财经大学 MBA奖学金
  • 手把手教你Linux的服务管理
  • 实验三 Windows窗体的设计及常用控件(1)
  • 【计算机毕业设计】java SpringBoot校园大学生志愿者服务系统
  • 【深入理解Kafka系列】第六章 __consumer_offsets(位移主题)
  • 脑机接口科普0008——侵入式与非侵入式
  • Nginx网站服务