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 ...
随机推荐
- DDMS查看Threads情况
有时候程序运行出现死锁或者信号量卡死是很纠结的问题,单看代码很难分析定位问题,这时候可以借助DDMS来查看threads的运行情况,一目了然. 手机连接上USB,确保adb连通,然后启动Eclipse ...
- WPF绘图(一):几何(Geometry)与形状(Shape)
1. Geometry 在数学中,我们可以用一个方程描述圆:x2+y2=25.这个方程描述的是,一个半径为5,中心点在(0,0)的圆.这种纯数学的描述就是Geometry(几何). 但此时,这个&qu ...
- QMainWindow无法显示,使用show()不显示窗口(QT)
当使用 MainWindow w: w.show(); 不显示窗口时 变更为: MainWindow *w=new MainWindow(); w->show();
- 在不知带头节点地址的情况下删除和插入一个p指针指向的节点总结
在不知带头节点地址的情况下删除和插入一个p指针指向的节点总结 (p指向的不是第一个,也不是最后一个)A->B->C *p->B 插入(在p结点之前插入q) 解析: 直接往p前插入q, ...
- Python:基础&爬虫
Python:基础&爬虫 Python爬虫学习(网络爬虫(又称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本.另 ...
- Ocserv整合Radius认证
目前社区主流SSL VPN有两个分支:openvpn和ocserv,通过官网和检索到的资料对比前者服务端比较强大,后者客户端和移动端支持更好,二者并不兼容: 另外前者商业化封装更好,偏向商业化,后者对 ...
- [Python急救站]密码判断
用Python做一个密码判断,用户输入注册密码,需要6位以上,包含数字.大写字母.小写字母. import re a = re.compile('[a-z]') b = re.compile('[A- ...
- inget
万能密码考点 payload ?id=1' or 1=1--+
- 多项目git账户用户名和邮箱设置以及局部github代理
因为公司使用自建的gitlab服务器所以需要配置两个git账户分别用来访问公司仓库和自己的github仓库. 前言: 首先给大家梳理一下多用户名或者说多邮箱使用git的理解误区.我们需要知道的是我们的 ...
- 【ASP.NET Core】MVC过滤器:常见用法
前面老周给大伙伴们演示了过滤器的运行流程,大伙只需要知道下面知识点即可: 1.过滤器分为授权过滤.资源访问过滤.操作方法(Action)过滤.结果过滤.异常过滤.终结点过滤.上一次咱们没有说异常过滤和 ...