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. Sunshine on my shoulders

    https://music.163.com/#/song?id=1477706 Sunshine on my shoulders makes me happy照在我肩上的阳光让我欢乐Sunshine ...

  2. 基于AI模型的验证码安全识别(B站,知乎等)

      bilibili 汉字识别顺序验证码 实现基本思路:    先利用Selenium模拟登录,当然在这之前做好请求伪装,get方法使边框最大化,并且将系统的windows窗口缩放比例设置为100%, ...

  3. postman导入请求到jmeter进行简单压测,开发同学一学就会

    背景 这个事情也是最近做的,因为线上nginx被我换成了openresty,然后接入层服务也做了较大改动,虽然我们这个app(内部办公类)并发不算高,但好歹还是压测一下,上线时心里也稳一点. 于是用j ...

  4. Chromium GPU资源共享

    资源共享指的是在一个 Context 中的创建的 Texture 资源可以被其他 Context 所使用.一般来讲只有相同 share group Context 创建的 Texture 才可以被共享 ...

  5. Kubernetes跨StorageClass迁移,切换Rainbond默认SC

    基于主机安装或基于Kubernetes安装的 Rainbond 集群(均使用默认参数安装),默认使用的共享文件存储是 NFS ,以 Pod 方式运行在 Kubernetes 中,但这种方式也有一些无法 ...

  6. Golang后端大厂面经!

    大家好,我是阳哥.专注Go语言的学习经验分享和就业辅导. 之前分享了很多 Golang 后端的大厂面经,不少同学在催更新,这篇给大家继续安排. 本文来自一位同学的投稿,面试深X服的面经汇总,前半部分主 ...

  7. Radius+OpenLdap+USG防火墙认证

    1.1.安装OpenLdap # 在数据目录创建ldap文件存放ldap的配置文件 mkdir -p /data/ldap/{data,conf} docker run -p 389:389 -p 6 ...

  8. File --JAVA

    File --JAVA 构造方法 方法 说明 public File (String pathname) 根据文件路径创建对象 public File (String parent, String c ...

  9. Axure RP Pro 6.5如何创建Tab标签效果(转)

    http://jingyan.baidu.com/article/ce09321b3c665f2bff858f01.html  Axure RP Pro 能帮助网站需求设计者,快捷而简便的创建基于网站 ...

  10. Git入门笔记--版本控制系统的使用

    首先记录下使用命令行工具git与github交互的 "Hello,World!" ."Hello,World!"是任何程序设计语言入门第一课,不管原理,先跑起来 ...