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基础——函数的理解、函数对象、函数嵌套、闭包函数、及其应用
文章目录 函数也是变量 可以赋值 可以当做函数当做参数传给另外一个函数 可以当做函数当做另外一个函数的返回值 可以当做容器类型的一个元素 函数对象应用示范 原始版 修正版 函数嵌套 函数的嵌套调用 函 ...
- 记一次Redis Cluster Pipeline导致的死锁问题
作者:vivo 互联网服务器团队- Li Gang 本文介绍了一次排查Dubbo线程池耗尽问题的过程.通过查看Dubbo线程状态.分析Jedis连接池获取连接的源码.排查死锁条件等方面,最终确认是因为 ...
- addEventListener学习
场景:给input框添加事件,但是里面的function得抽取出来复用,并且这个function还要传递参数 userId.addEventListener('input', idTest(userI ...
- 2D物理引擎 Box2D for javascript Games 第六章 关节和马达
2D物理引擎 Box2D for javascript Games 第六章 关节和马达 关节和马达 到现在你所见到的所有类型的刚体有着一些共同点:它们都是自由的并且在除碰撞的请款之外,彼此没有依赖. ...
- 实用的命令行终端增强软件:Tabby
还是那句话:出众的软件有很多,适合自己的才是最好的. 一.软件介绍 Tabby是一个开源免费软件,支持Windows.macOS和Linux系统.它提供了一个高度可定制的终端界面,可以通过多种方式添加 ...
- SpringBoot数据响应、分层解耦、三层架构
响应数据 @ResponseBody 类型:方法注解.类注解 位置:Controller方法.类上 作用:将方法返回值直接响应,如果返回值类型是 实体对象/集合 ,将会转换为json格式响应 说明:@ ...
- zookeeper源码(04)leader选举流程
在"zookeeper源码(03)集群启动流程"中介绍了leader选举的入口,本文将详细分析leader选举组件和流程. leader选举流程(重要) quorumPeer的st ...
- 混合应用与Hybrid App开发上架流程透析
Hybrid App(混合 App)已经成为大家接触最为广泛的 App 形式,不管是我们用到的微信.支付宝还是淘宝.京东等大大小小的应用都非常热衷于Hybrid App 带来的研发效率提升和灵活性. ...
- 义无反顾马督工,Bert-vits2V210复刻马督工实践(Python3.10)
Bert-vits2更新了版本V210,修正了日/英的bert对齐问题,效果进一步优化:对底模使用的数据进行优化和加量,减少finetune失败以及电音的可能性:日语bert更换了模型,完善了多语言推 ...
- 旺店通·企业奇门与用友BIP旺店通销售出库单对接销售订单
源系统平台:旺店通·企业奇门 源系统接口: 查询销售出库单wdt.stockout.order.query.trade 目标系统平台: 用友BIP目标系统接口: 销售订单单个保存/yonbip/sd/ ...