首页 > 其他分享 >2023-07-07:给出两个字符串 str1 和 str2。 返回同时以 str1 和 str2 作为子序列的最短字符串。 如果答案不止一个,则可以返回满足条件的任意一个答案。 输入:str1 =

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

时间:2023-07-07 22:46:11浏览次数:45  
标签:07 -- str2 str1 ansi ans dp

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;
}

在这里插入图片描述

标签:07,--,str2,str1,ansi,ans,dp
From: https://www.cnblogs.com/moonfdd/p/17536229.html

相关文章

  • 2023-07-07:给出两个字符串 str1 和 str2。 返回同时以 str1 和 str2 作为子序列的最短
    2023-07-07:给出两个字符串str1和str2。返回同时以str1和str2作为子序列的最短字符串。如果答案不止一个,则可以返回满足条件的任意一个答案。输入:str1="abac",str2="cab"。输出:"cabac"。答案2023-07-07:大体步骤如下:1.初始化字符串str1和str2分别为"abac"和"cab"......
  • [oeasy]python0071_字符串类型_str_string_下标运算符_中括号
    回忆上次内容上次分辨了静态类型语言动态类型语言 python属于对类型要求没有那么严格的动态类型语言 对初学者很友好不过很多时候也容易弄不清变量类型 直接修改代码增强程序的可读性把变量的类型明确标......
  • 20230706巴蜀暑期集训测试总结
    T1我是个大聪明!一眼矩乘。构造转移矩阵构造了3.5h!最开始以为只有\(15\times15\),直接手打。写到一半发现不一定四种颜色都有,是\(52\times52\)的,这时候狗被脑子吃了,还想手打,于是就打到了3h。差不多打了一大半,脑子终于把狗还回来了,意识到就算打完也不可能调得出来,就开始另辟蹊径,......
  • 7.07日
    昨晚洗完澡躺在床上就睡着了,早上八点多醒来一次,十点多又醒一次,最后十二点十七分才醒。妈妈从外面打包的回锅肉盖饭,简单抹一把脸,吃完饭后再进行洗漱。今天还是进PTA敲代码,实验报告太磨人了。连着写了两道题都是编译错误,可是本地运行也没错呀。上网搜索寻找解决办法,好嘛这次格式错误......
  • 20230707巴蜀暑期集训测试总结
    T1SPFA就能过!给我震惊到了。可以斜率优化。对每个站点维护一个凸包。\[f(x)=Ax^2+Bx+C\\dp_{v,q}=\min_{i=0}^{p}\{dp_{u,i}+f(p-i)\}\\(i,dp_{x,i}+Ai^2-Bi)\]T2考场想了想区间dp,有点思路但是时间不多了有点慌,打个暴搜直接跑。相当于将位置当作第二关键字比较,最大的数......
  • 1.6.07 有趣的跳跃
    1.题目描述一个长度为n(n>0)的序列中存在“有趣的跳跃”当前仅当相邻元素的差的绝对值经过排序后正好是从1到(n-1)。例如,1423存在“有趣的跳跃”,因为差的绝对值分别为3,2,1。当然,任何只包含单个元素的序列一定存在“有趣的跳跃”。你需要写一个程序判定给定序列是否存在“有趣......
  • 2023-07-07 《数值优化方法》-庞丽萍,肖现涛-无约束最优化(三).md
    2023-07-07《数值优化方法》-庞丽萍,肖现涛-无约束最优化(三)数值优化方法Matlab一维线搜索牛顿法抛物线法非精确线搜索1.牛顿法书接上回,对于一维最优化问题,牛顿法是在迭代点处进行二次泰勒展开来近似原函数,然后求泰勒展开式的极小点,具体如下设为当前迭代点,在处的二阶泰勒......
  • 「NOIP 模拟赛 20230707」T2 - 涂照片 题解
    题目大意原题有一个\(n+1\timesm+1\)的网格。对于每一行\(i\),都要将左侧的一些格子\((i,1),(i,2),\ldots,(i,x)\)涂黑,其中\(x=k\)的概率为\(a_{i,k}\)。同理对于每一列\(j\),都要将上方的一些格子\((1,j),(2,j),\ldots,(x,j)\)涂黑,其中\(x=k\)的概率为\(b_{k,......
  • 230707 // 换根复习续
    A.叶子的染色http://222.180.160.110:1024/contest/3824/problem/1不难发现题目非常难以看懂。其实题目的意思是,\(1\simn\)一定是叶子节点(就不能明说吗)。那么问题来了,这是一棵无根树,那么我们所选取的根会对答案造成影响吗?由于\(c_u\)给定的是根节点到\(u\)路径上最后......
  • Day04(2023.07.07)
    行程9:00到达上海城建城市运营有限公司(黄浦区打浦路600号)10:00整理编写文档11:30--13:00吃饭休息13:00学习等保测评基础知识,见《等保测评基础知识》16:30下班......