2023-07-07:给出两个字符串 str1 和 str2。 返回同时以 str1 和 str2 作为子序列的最短字符串。 如果答案不止一个,则可以返回满足条件的任意一个答案。 输入:str1 =
2023-07-07:给出两个字符串 str1 和 str2。
返回同时以 str1 和 str2 作为子序列的最短字符串。
如果答案不止一个,则可以返回满足条件的任意一个答案。
输入:str1 = "abac", str2 = "cab"。
输出:"cabac"。
答案2023-07-07:
大体步骤如下:
1.初始化字符串 str1 和 str2 分别为 "abac" 和 "cab"。
2.创建一个二维数组 dp,其大小为 (n+1) x (m+1),其中 n 是 str1 的长度,m 是 str2 的长度。
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.初始化变量 ansi 为 len(ans) - 1,i 为 n,j 为 m。
7.通过回溯 dp 数组,从右下角开始往左上角移动,直到 i 和 j 达到边界 0。
8.如果 dp[i][j] 等于 dp[i-1][j-1] + 1 且 str1[i-1] 等于 str2[j-1],表示当前字符是在 str1 和 str2 的最短公共超序列中,将其存入 ans 中并将 ansi 减一,同时将 i 和 j 减一。
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 =的更多相关文章
- [Robot Framework] 校验字符串中是否包含某个子字符串,校验同时满足两个条件中任意一个
${tWarningMessage} Run Keyword If ${tIfExist} AutoItLibrary.Win Get Text Generate Fee Data warning m ...
- VIM 用正则表达式,非贪婪匹配,匹配竖杠,竖线, 匹配中文,中文正则,倒数第二列, 匹配任意一个字符 :
VIM 用正则表达式 批量替换文本,多行删除,复制,移动 在VIM中 用正则表达式 批量替换文本,多行删除,复制,移动 :n1,n2 m n3 移动n1-n2行(包括n1,n2)到n3行之下: ...
- pojg2744找一个最长的字符串x,使得对于已经给出的字符串中的任意一个y,x或者是y的子串,或者x中的字符反序之后得到的新字符串是y的子串。
http://poj.grids.cn/practice/2744 描述现在有一些由英文字符组成的大小写敏感的字符串,你的任务是找到一个最长的字符串x,使得对于已经给出的字符串中的任意一个y,x或者是 ...
- 算法 - 给出一个字符串str,输出包含两个字符串str的最短字符串,如str为abca时,输出则为abcabca
今天碰到一个算法题觉得比较有意思,研究后自己实现了出来,代码比较简单,如发现什么问题请指正.思路和代码如下: 基本思路:从左开始取str的最大子字符串,判断子字符串是否为str的后缀,如果是则返回st ...
- 剑指offer17:输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
1 题目描述 输入两棵二叉树A,B,判断B是不是A的子结构.(ps:我们约定空树不是任意一个树的子结构) 2 思路和方法 (1)先在A中找和B的根节点相同的结点 (2)找到之后遍历对应位置的其他结点, ...
- 给出两个单词word1和word2,写一个函数计算出将word1 转换为word2的最少操作次数。
问题: 给出两个单词word1和word2,写一个函数计算出将word1 转换为word2的最少操作次数. 你总共三种操作方法: 1.插入一个字符 2.删除一个字符 3.替换一个字符 格式: 输入行输 ...
- 剑指offer25:复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),结果返回复制后复杂链表的head。
1 题目描述 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head.(注意,输出结果中请不要返回参数中的节点引用 ...
- 输入n个字符串,找出最长最短字符串(若有个数相同的,都打印出来)
首先,要求找到最长最短字符串,我们应该用数组将其存起来,输入的个数是不固定的,我们就可以用Scanner获取要输入的个数,最终找到的个数也不固定,我们可以封装两个方法,并且返回值类型为数组. 我遇到的 ...
- 给定任意一个字符串,使用 for in 语句来统计字符出现的个数
//找出字符串中的数字 var str = 'haj123sdk54hask33dkhalsd879'; /*function findNum(str){ var arr = []; var tmp ...
- [java面试]逻辑推理6 10 18 32 下一个数?编程实现输入任意一个N位置,该数是多少?java实现
题目: 6 10 18 32 下一个数?编程实现输入任意一个N位置,该数是多少? 10 = 6 + 4 4 18 = 10 + 8 4 + 4 32 = 18 + 14 ...
随机推荐
- Python基础—— 模块介绍、模块的使用、包介绍、 包的使用、软件开发目录规范
文章目录 一 模块介绍 二 模块的使用 2.1 import语句 2.2 from-import 语句 2.3 其他导入语法(as) 2.4 循环导入问题 2.5 搜索模块的路径与优先级 2.6 区分 ...
- options has an unknown property ‘contentBase‘
options has an unknown property 'contentBase' 踩坑新版webpack-dev-serve 新版的contentBase取消了替代属性是static
- Lab3 存储过程与触发器
实验三 存储过程与触发器 实验目的: 学习SQL语言进行编程的基本方法与技术,能够编写存储过程.触发器解决数据库需要处理的复杂问题. 实验内容: 1. 设计一个存储过程或者自定义函数,练习存储 ...
- 循序渐进介绍基于CommunityToolkit.Mvvm 和HandyControl的WPF应用端开发(9) -- 实现系统动态菜单的配置和权限分配
在WPF应用端开发,它的界面类似于Winform端,因此我们也需要对系统的菜单进行动态配置,这样才能把系统的功能弹性发挥到极致,通过动态菜单的配置方式,我们可以很容易的为系统新增所需的功能,通过权限分 ...
- chatgpt镜像站汇总 - 聚合GPT【即时更新】
自荐下由我开发的聚合GPT网站,这边的GPT镜像站均为免费.无登录.无次数限制的!会及时剔除失效.添加可用地址[欢迎STAR.PR] 地址:https://ele-cat.gitee.io/comp- ...
- 一文搞懂深度信念网络!DBN概念介绍与Pytorch实战
本文深入探讨了深度信念网络DBN的核心概念.结构.Pytorch实战,分析其在深度学习网络中的定位.潜力与应用场景. 关注TechLead,分享AI与云服务技术的全维度知识.作者拥有10+年互联网服务 ...
- U盘插入过手机后再拔出来,windows无法识别的解决办法
win键+X,设备管理器. 找到"通用串行总线控制器",大容量USB设备,右键,卸载设备. 拔出U盘,再插入U盘. 就好了. 很明显,U盘插入手机,然后设置里点弹出后再拔,这是很规 ...
- django admin字段设置大全
# 在列表页显示的字段,默认会显示所有字段,有对应的方法可以重写 list_display = ('__str__',) # 在列表页显示的字段中,可以链接到change_form页面的字段 list ...
- Python JSON 使用指南:解析和转换数据
JSON 是一种用于存储和交换数据的语法.JSON 是文本,使用 JavaScript 对象表示法编写. Python 中的 JSON Python 有一个内置的 json 包,可用于处理 JSON ...
- C++基础杂记(1)
结构体中的位字段 共用体 烦人的枚举 枚举的声明与赋值 枚举的取值范围与强制类型转换 枚举的注意事项 指针 为什么是 int* ptr 而不是 int *ptr ? 避免危险的指针 使用array和v ...