2023-07-07:给出两个字符串 str1 和 str2。

返回同时以 str1 和 str2 作为子序列的最短字符串。

如果答案不止一个,则可以返回满足条件的任意一个答案。

输入:str1 = "abac", str2 = "cab"。

输出:"cabac"。

答案2023-07-07:

大体步骤如下:

1.初始化字符串 str1str2 分别为 "abac" 和 "cab"。

2.创建一个二维数组 dp,其大小为 (n+1) x (m+1),其中 nstr1 的长度,mstr2 的长度。

3.使用动态规划来填充 dp 数组。循环遍历 i 从 1 到 n,以及 j 从 1 到 m

4.在每个循环中,比较 str1[i-1]str2[j-1] 的值:

  • 如果它们相等,更新 dp[i][j]dp[i-1][j-1] + 1,表示当前字符能够在最短公共超序列中出现。

  • 否则,取 dp[i-1][j]dp[i][j-1] 中的较大值,表示当前字符不能同时出现在最短公共超序列中,需要从其中一个字符串中选择。

5.创建一个长度为 n + m - dp[n][m] 的字符数组 ans,用于存储最短公共超序列。

6.初始化变量 ansilen(ans) - 1injm

7.通过回溯 dp 数组,从右下角开始往左上角移动,直到 ij 达到边界 0。

8.如果 dp[i][j] 等于 dp[i-1][j-1] + 1str1[i-1] 等于 str2[j-1],表示当前字符是在 str1str2 的最短公共超序列中,将其存入 ans 中并将 ansi 减一,同时将 ij 减一。

9.如果 dp[i][j] 等于 dp[i-1][j],表示当前字符只出现在 str1 中,将其存入 ans 中并将 ansi 减一,同时将 i 减一。

10.如果 dp[i][j] 等于 dp[i][j-1],表示当前字符只出现在 str2 中,将其存入 ans 中并将 ansi 减一,同时将 j 减一。

11.当完成回溯后,若 i 大于 0,将 str1 中剩余的字符存入 ans 中。

12.当完成回溯后,若 j 大于 0,将 str2 中剩余的字符存入 ans 中。

13.将 ans 转换为字符串,并作为结果返回。

14.在 main 函数中调用 shortestCommonSupersequence 函数,并输出结果 "cabac"。

时间复杂度:O(nm),其中 n 是字符串 str1 的长度,m 是字符串 str2 的长度。

空间复杂度:O(nm),需要使用一个二维数组 dp 来存储中间结果。

这是使用动态规划(Dynamic Programming)解决字符串相关问题的算法。具体来说,这个算法用于找到两个字符串的最短公共超序列(Shortest Common Supersequence)。最短公共超序列是指包含两个字符串的所有字符,并且是长度最短的序列。通过使用动态规划的方法,可以利用子问题的最优解来构建整体的最优解,从而高效地解决这个问题。

go完整代码如下:

package main

import (
"fmt"
) func shortestCommonSupersequence(str1 string, str2 string) string {
n := len(str1)
m := len(str2)
dp := make([][]int, n+1)
for i := range dp {
dp[i] = make([]int, m+1)
}
for i := 1; i <= n; i++ {
for j := 1; j <= m; j++ {
dp[i][j] = max(dp[i-1][j], dp[i][j-1])
if str1[i-1] == str2[j-1] {
dp[i][j] = max(dp[i][j], dp[i-1][j-1]+1)
}
}
}
ans := make([]byte, n+m-dp[n][m])
ansi := len(ans) - 1
i := n
j := m
for i > 0 && j > 0 {
if dp[i][j] == dp[i-1][j-1]+1 && str1[i-1] == str2[j-1] {
ans[ansi] = str1[i-1]
ansi--
i--
j--
} else if dp[i][j] == dp[i-1][j] {
ans[ansi] = str1[i-1]
ansi--
i--
} else {
ans[ansi] = str2[j-1]
ansi--
j--
}
}
for ; i > 0; i-- {
ans[ansi] = str1[i-1]
ansi--
}
for ; j > 0; j-- {
ans[ansi] = str2[j-1]
ansi--
}
return string(ans)
} func max(a, b int) int {
if a > b {
return a
}
return b
} func main() {
str1 := "abac"
str2 := "cab"
result := shortestCommonSupersequence(str1, str2)
fmt.Println(result)
}

rust完整代码如下:

fn shortest_common_supersequence(str1: &str, str2: &str) -> String {
let s1: Vec<char> = str1.chars().collect();
let s2: Vec<char> = str2.chars().collect();
let n = s1.len();
let m = s2.len();
let mut dp = vec![vec![0 as i32; m + 1]; n + 1]; let mut i = 1; while i <= n {
let mut j = 1;
while j <= m {
dp[i][j] = dp[i - 1][j].max(dp[i][j - 1]);
if s1[i - 1] == s2[j - 1] {
dp[i][j] = dp[i][j].max(dp[i - 1][j - 1] + 1);
}
j += 1;
}
i += 1;
} let ans_length = n + m - dp[n][m] as usize;
let mut ans = vec![' '; ans_length];
let mut ansi = ans_length as i32 - 1;
let (mut i, mut j) = (n, m); while i > 0 && j > 0 {
if dp[i][j] == dp[i - 1][j - 1] + 1 && str1.chars().nth(i - 1) == str2.chars().nth(j - 1) {
ans[ansi as usize] = str1.chars().nth(i - 1).unwrap();
ansi -= 1;
i -= 1;
j -= 1;
} else if dp[i][j] == dp[i - 1][j] {
ans[ansi as usize] = str1.chars().nth(i - 1).unwrap();
ansi -= 1;
i -= 1;
} else {
ans[ansi as usize] = str2.chars().nth(j - 1).unwrap();
ansi -= 1;
j -= 1;
}
} while i > 0 {
ans[ansi as usize] = str1.chars().nth(i - 1).unwrap();
ansi -= 1;
i -= 1;
} while j > 0 {
ans[ansi as usize] = str2.chars().nth(j - 1).unwrap();
ansi -= 1;
j -= 1;
} ans.iter().collect()
} fn main() {
let str1 = String::from("abac");
let str2 = String::from("cab"); let result = shortest_common_supersequence(&str1, &str2);
println!("{}", result);
}

c++完整代码如下:

#include <iostream>
#include <vector>
#include <string> using namespace std; string shortestCommonSupersequence(string str1, string str2) {
int n = str1.size();
int m = str2.size();
vector<vector<int>> dp(n + 1, vector<int>(m + 1, 0)); for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
if (str1[i - 1] == str2[j - 1]) {
dp[i][j] = max(dp[i][j], dp[i - 1][j - 1] + 1);
}
}
} string ans;
int i = n;
int j = m; while (i > 0 && j > 0) {
if (dp[i][j] == dp[i - 1][j - 1] + 1 && str1[i - 1] == str2[j - 1]) {
ans = str1[i - 1] + ans;
i--;
j--;
}
else if (dp[i][j] == dp[i - 1][j]) {
ans = str1[i - 1] + ans;
i--;
}
else {
ans = str2[j - 1] + ans;
j--;
}
} while (i > 0) {
ans = str1[i - 1] + ans;
i--;
} while (j > 0) {
ans = str2[j - 1] + ans;
j--;
} return ans;
} int main() {
string str1 = "abac";
string str2 = "cab"; string result = shortestCommonSupersequence(str1, str2);
cout << result << endl; return 0;
}

c完整代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h> char* shortestCommonSupersequence(char* str1, char* str2) {
int n = strlen(str1);
int m = strlen(str2);
int** dp = (int**)malloc((n + 1) * sizeof(int*));
for (int i = 0; i <= n; i++) {
dp[i] = (int*)malloc((m + 1) * sizeof(int));
memset(dp[i], 0, (m + 1) * sizeof(int));
} for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
dp[i][j] = (dp[i - 1][j] > dp[i][j - 1]) ? dp[i - 1][j] : dp[i][j - 1];
if (str1[i - 1] == str2[j - 1]) {
dp[i][j] = (dp[i][j] > dp[i - 1][j - 1] + 1) ? dp[i][j] : dp[i - 1][j - 1] + 1;
}
}
} int len = n + m - dp[n][m];
char* ans = (char*)malloc((len + 1) * sizeof(char));
ans[len] = '\0';
int ansi = len - 1;
int i = n;
int j = m; while (i > 0 && j > 0) {
if (dp[i][j] == dp[i - 1][j - 1] + 1 && str1[i - 1] == str2[j - 1]) {
ans[ansi--] = str1[i - 1];
i--;
j--;
}
else if (dp[i][j] == dp[i - 1][j]) {
ans[ansi--] = str1[i - 1];
i--;
}
else {
ans[ansi--] = str2[j - 1];
j--;
}
} for (; i > 0; i--) {
ans[ansi--] = str1[i - 1];
}
for (; j > 0; j--) {
ans[ansi--] = str2[j - 1];
} for (int i = 0; i <= n; i++) {
free(dp[i]);
}
free(dp); return ans;
} int main() {
char str1[] = "abac";
char str2[] = "cab"; char* result = shortestCommonSupersequence(str1, str2);
printf("%s\n", result); free(result);
return 0;
}

2023-07-07:给出两个字符串 str1 和 str2。 返回同时以 str1 和 str2 作为子序列的最短字符串。 如果答案不止一个,则可以返回满足条件的任意一个答案。 输入:str1 =的更多相关文章

  1. [Robot Framework] 校验字符串中是否包含某个子字符串,校验同时满足两个条件中任意一个

    ${tWarningMessage} Run Keyword If ${tIfExist} AutoItLibrary.Win Get Text Generate Fee Data warning m ...

  2. VIM 用正则表达式,非贪婪匹配,匹配竖杠,竖线, 匹配中文,中文正则,倒数第二列, 匹配任意一个字符 :

    VIM 用正则表达式 批量替换文本,多行删除,复制,移动 在VIM中 用正则表达式 批量替换文本,多行删除,复制,移动 :n1,n2 m n3     移动n1-n2行(包括n1,n2)到n3行之下: ...

  3. pojg2744找一个最长的字符串x,使得对于已经给出的字符串中的任意一个y,x或者是y的子串,或者x中的字符反序之后得到的新字符串是y的子串。

    http://poj.grids.cn/practice/2744 描述现在有一些由英文字符组成的大小写敏感的字符串,你的任务是找到一个最长的字符串x,使得对于已经给出的字符串中的任意一个y,x或者是 ...

  4. 算法 - 给出一个字符串str,输出包含两个字符串str的最短字符串,如str为abca时,输出则为abcabca

    今天碰到一个算法题觉得比较有意思,研究后自己实现了出来,代码比较简单,如发现什么问题请指正.思路和代码如下: 基本思路:从左开始取str的最大子字符串,判断子字符串是否为str的后缀,如果是则返回st ...

  5. 剑指offer17:输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)

    1 题目描述 输入两棵二叉树A,B,判断B是不是A的子结构.(ps:我们约定空树不是任意一个树的子结构) 2 思路和方法 (1)先在A中找和B的根节点相同的结点 (2)找到之后遍历对应位置的其他结点, ...

  6. 给出两个单词word1和word2,写一个函数计算出将word1 转换为word2的最少操作次数。

    问题: 给出两个单词word1和word2,写一个函数计算出将word1 转换为word2的最少操作次数. 你总共三种操作方法: 1.插入一个字符 2.删除一个字符 3.替换一个字符 格式: 输入行输 ...

  7. 剑指offer25:复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),结果返回复制后复杂链表的head。

    1 题目描述 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head.(注意,输出结果中请不要返回参数中的节点引用 ...

  8. 输入n个字符串,找出最长最短字符串(若有个数相同的,都打印出来)

    首先,要求找到最长最短字符串,我们应该用数组将其存起来,输入的个数是不固定的,我们就可以用Scanner获取要输入的个数,最终找到的个数也不固定,我们可以封装两个方法,并且返回值类型为数组. 我遇到的 ...

  9. 给定任意一个字符串,使用 for in 语句来统计字符出现的个数

    //找出字符串中的数字 var str = 'haj123sdk54hask33dkhalsd879'; /*function findNum(str){ var arr = []; var tmp ...

  10. [java面试]逻辑推理6 10 18 32 下一个数?编程实现输入任意一个N位置,该数是多少?java实现

    题目: 6 10 18 32 下一个数?编程实现输入任意一个N位置,该数是多少? 10 = 6 + 4         4 18 = 10 + 8        4 + 4  32 = 18 + 14 ...

随机推荐

  1. Python基础——函数的理解、函数对象、函数嵌套、闭包函数、及其应用

    文章目录 函数也是变量 可以赋值 可以当做函数当做参数传给另外一个函数 可以当做函数当做另外一个函数的返回值 可以当做容器类型的一个元素 函数对象应用示范 原始版 修正版 函数嵌套 函数的嵌套调用 函 ...

  2. 记一次Redis Cluster Pipeline导致的死锁问题

    作者:vivo 互联网服务器团队- Li Gang 本文介绍了一次排查Dubbo线程池耗尽问题的过程.通过查看Dubbo线程状态.分析Jedis连接池获取连接的源码.排查死锁条件等方面,最终确认是因为 ...

  3. addEventListener学习

    场景:给input框添加事件,但是里面的function得抽取出来复用,并且这个function还要传递参数 userId.addEventListener('input', idTest(userI ...

  4. 2D物理引擎 Box2D for javascript Games 第六章 关节和马达

    2D物理引擎 Box2D for javascript Games 第六章 关节和马达 关节和马达 到现在你所见到的所有类型的刚体有着一些共同点:它们都是自由的并且在除碰撞的请款之外,彼此没有依赖. ...

  5. 实用的命令行终端增强软件:Tabby

    还是那句话:出众的软件有很多,适合自己的才是最好的. 一.软件介绍 Tabby是一个开源免费软件,支持Windows.macOS和Linux系统.它提供了一个高度可定制的终端界面,可以通过多种方式添加 ...

  6. SpringBoot数据响应、分层解耦、三层架构

    响应数据 @ResponseBody 类型:方法注解.类注解 位置:Controller方法.类上 作用:将方法返回值直接响应,如果返回值类型是 实体对象/集合 ,将会转换为json格式响应 说明:@ ...

  7. zookeeper源码(04)leader选举流程

    在"zookeeper源码(03)集群启动流程"中介绍了leader选举的入口,本文将详细分析leader选举组件和流程. leader选举流程(重要) quorumPeer的st ...

  8. 混合应用与Hybrid App开发上架流程透析

    Hybrid App(混合 App)已经成为大家接触最为广泛的 App 形式,不管是我们用到的微信.支付宝还是淘宝.京东等大大小小的应用都非常热衷于Hybrid App 带来的研发效率提升和灵活性. ...

  9. 义无反顾马督工,Bert-vits2V210复刻马督工实践(Python3.10)

    Bert-vits2更新了版本V210,修正了日/英的bert对齐问题,效果进一步优化:对底模使用的数据进行优化和加量,减少finetune失败以及电音的可能性:日语bert更换了模型,完善了多语言推 ...

  10. 旺店通·企业奇门与用友BIP旺店通销售出库单对接销售订单

    源系统平台:旺店通·企业奇门 源系统接口: 查询销售出库单wdt.stockout.order.query.trade 目标系统平台: 用友BIP目标系统接口: 销售订单单个保存/yonbip/sd/ ...