首页 > 其他分享 >实验2-1

实验2-1

时间:2023-11-24 23:11:25浏览次数:28  
标签:int MAX -- LENGTH 实验 序列 dp

实验2-1 最长公共子序列

如题:实验2-1

思路:

很明显的动态规划问题

找出递推公式,《计算机算法设计与分析第五版 王晓东》p55

建议画图理解

s1==s2

s1!=s2

然后填表

s1= a b c f b c s2= a b f c a b (第一组数据)

a b c f b c
0 0 0 0 0 0 0
a 0 1 1 1 1 1 1
b 0 1 2 2 2 2 2
f 0 1 2 2 3 3 3
c 0 1 2 3 3 3 4
a 0 1 2 3 3 3 4
b 0 1 2 3 3 4 4

以a行举例

a比a一样,所以 a行a列 0+1=1 (根据公式i-1,j-1 0行0列的值+1)

a比b不一样,所以max(1,0),填1

a比c不一样,填1

a比f不一样,填1

a比b不一样,填1

a比c不一样,填1

怎么根据表找最大公共子串反推

答案明显不唯一,注意题目:以第一个串中字符的出现次序优先

a b c f b c为第一串:

也可以这样找

a b f c a b为第一串:

the same

代码:

#include <stdio.h>
#include <string.h>

#define MAX_LENGTH 100

//动态规划
void LCS(char t[], char s[]) {

    int m = strlen(s);
    int n = strlen(t);
    
    //二维数组dp,保存最长公共子序列的长度
    int dp[MAX_LENGTH+1][MAX_LENGTH+1];
    
    //初始化
    memset(dp, 0, sizeof(dp));
    
    for (int i = 1; i <= m; i++) {  //比对 二维数组或者说是矩阵 里面的值 并给计算每行每列的值(使用递推公式)
        
        for (int j = 1; j <= n; j++) {
            //如果s和t的当前字符相等,则公共子序列的长度为前一个状态的长度加1
            if (s[i - 1] == t[j - 1]) {
                dp[i][j] = dp[i - 1][j - 1] + 1;
            } 
            else {
                //否则,公共子序列的长度取前一个状态中较大值
                dp[i][j] = (dp[i - 1][j] > dp[i][j - 1]) ? dp[i - 1][j] : dp[i][j - 1];
            }
        }
    }
    
    //最长公共子序列的长度
    printf("%d\n", dp[m][n]);
    
    //构造最长公共子序列
    char lcs[MAX_LENGTH];
    int i = m;
    int j = n;
    int index = dp[m][n]; //根据规划表,进行反推最长子序列,每找到一个字符减 1


    while (i > 0 && j > 0) {
        if (s[i - 1] == t[j - 1]) {
            //如果当前字符相等,则将该字符添加到最长公共子序列中
            lcs[--index] = s[i - 1];
            i--;
            j--;
        } 
        else if (dp[i - 1][j] > dp[i][j - 1]) {
            //进行位置向上移动
            i--;
        } 
        else {
            //位置向左移动
            j--;
        }
    }
    
    //输出最长公共子序列
    for (int k = 0; k < dp[m][n]; k++) {

        printf("%c", lcs[k]);
    }
}

int main() {

    int T;
    scanf("%d", &T);
    
    for (int i = 0; i < T; i++) {

        char s[MAX_LENGTH], t[MAX_LENGTH];
        scanf("%99s%99s", s, t);
        LCS(s, t);
        if(i < (T-1)){
            printf("\n");
        }
          
    }

    return 0;
}

还是太菜了

PTA一直显示答案错误

不!冷静分析一番,应该是输出的问题,题目暗示用字符串,但是c语言没有string类

改成C++

#include<iostream>
#include<string>
#include<algorithm> 

#define MAX_LENGTH 1000

//动态规划
void LCS(std::string t, std::string s) {
    int m = s.length();
    int n = t.length();

    //二维数组dp,保存最长公共子序列的长度
    int dp[MAX_LENGTH + 1][MAX_LENGTH + 1];

// 初始化
for (int i = 0; i <= m; i++) {
    std::fill(dp[i], dp[i] + n + 1, 0);
}

    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++) {
            //如果s和t的当前字符相等,则公共子序列的长度为前一个状态的长度加1
            if (s[i - 1] == t[j - 1]) {
                dp[i][j] = dp[i - 1][j - 1] + 1;
            } else {
                //否则,公共子序列的长度取前一个状态中较大值
                dp[i][j] = (dp[i - 1][j] > dp[i][j - 1]) ? dp[i - 1][j] : dp[i][j - 1];
            }
        }
    }

    //最长公共子序列的长度
    std::cout << dp[m][n] << std::endl;

    //构造最长公共子序列
    char lcs[MAX_LENGTH];
    int i = m;
    int j = n;
    int index = dp[m][n];

    while (i > 0 && j > 0) {
        if (s[i - 1] == t[j - 1]) {
            //如果当前字符相等,则将该字符添加到最长公共子序列中
            lcs[--index] = s[i - 1];
            i--;
            j--;
        } else if (dp[i - 1][j] > dp[i][j - 1]) {
            //进行位置向上移动
            i--;
        } else {
            //位置向左移动
            j--;
        }
    }

    //输出最长公共子序列
    for (int k = 0; k < dp[m][n]; k++) {
        std::cout << lcs[k];
    }
}

int main() {
    int T;
    std::cin >> T;

    for (int i = 0; i < T; i++) {
        std::string s, t;
        std::cin >> s >> t;
        LCS(s, t);
        if (i < (T - 1)) {
            std::cout << std::endl;
        }
    }

    return 0;
}

标签:int,MAX,--,LENGTH,实验,序列,dp
From: https://www.cnblogs.com/kirei7/p/17854987.html

相关文章

  • 实验4:抽象工厂模式
    软件设计                 石家庄铁道大学信息学院 实验4:抽象工厂模式本次实验属于模仿型实验,通过本次实验学生将掌握以下内容:1、理解抽象工厂模式的动机,掌握该模式的结构;2、能够利用抽象工厂模式解决实际问题。 [实验任务一]:人与肤色使用抽象工厂模......
  • 实验2:简单工厂模式
    软件设计                 石家庄铁道大学信息学院 实验2:简单工厂模式本次实验属于模仿型实验,通过本次实验学生将掌握以下内容:1、理解简单工厂模式的动机,掌握该模式的结构;2、能够利用简单工厂模式解决实际问题。 [实验任务一]:女娲造人使用简单工厂模......
  • 实验3:工厂方法模式
    实验3:工厂方法模式本次实验属于模仿型实验,通过本次实验学生将掌握以下内容:1、理解工厂方法模式的动机,掌握该模式的结构;2、能够利用工厂方法模式解决实际问题。 [实验任务一]:加密算法目前常用的加密算法有DES(DataEncryptionStandard)和IDEA(InternationalDataEncryption......
  • 实验1:UML与面向对象程序设计原则
    实验1:UML与面向对象程序设计原则本次实验属于模仿型实验,通过本次实验学生将掌握以下内容:1、掌握面向对象程序设计中类与类之间的关系以及对应的UML类图;2、理解面向对象程序设计原则。 [实验任务一]:UML复习阅读教材第一章复习UML,回答下述问题:面向对象程序设计中类与类的关......
  • Java实验报告五
    实验五实验名称:文件与I/O流实验目的:掌握文件与输入输出流的使用。实验时间:(2学时)实验类型:验证型实验内容:1.创建类:FindFile.java,遍历当前目录,打印目录中文件名称,目录打印”isDirectory”,文件打印“isfile”。修改程序打印当前目录及子目录信息。提示:当前目录名用......
  • Java实验报告
    实验一实验名称:JAVA中循环结构实验目的:熟悉循环结构,熟悉JAVA类的定义以及参数的传递。实验时间:(2学时)实验类型:验证型实验内容:(1)金字塔:Pyramid.java在屏幕上显示一个由星型符号“*”组成的金字塔图案,要求用户设置金字塔的高度,程序能根据用户设置的高度打印金字塔,......
  • 大数据实验(HBase基础操作)
    (一)Hadoop提供的HBaseShell命令完成任务要想将这些编码显示为中文,我们需要在get命令后添加一个属性:{FORMATTER=>'toString'}  (1)列出hbase所有表信息  (2)打印表的所有数据(3)添加、删除指定列族或列(4)清空指定表的数据(先禁用表在清空)(5)统计行数 (二)HBase数据库操......
  • 实验1-2
    实验1-2如题:思路:使用动态规划的思想(DP思路,即一个大一点规模的问题可以被拆解为更小的,更容易解决的问题)首先,定义一个数组dp,用来存储每个数的分解式个数。dp[i]表示当前数i的不同分解式的个数。接下来,从数2开始循环,逐个计算每个数的分解式个数。dp[i]=0,防止数组越界......
  • 11.23实验19
    实验19:中介者模式本次实验属于模仿型实验,通过本次实验学生将掌握以下内容:1、理解中介者模式的动机,掌握该模式的结构;2、能够利用中介者模式解决实际问题。[实验任务一]:虚拟聊天室在“虚拟聊天室”实例中增加一个新的具体聊天室类和一个新的具体会员类,要求如下:1.新的具体聊天室中......
  • 11.23实验20
    实验20:备忘录模式本次实验属于模仿型实验,通过本次实验学生将掌握以下内容:1、理解备忘录模式的动机,掌握该模式的结构;2、能够利用备忘录模式解决实际问题。[实验任务一]:多次撤销改进课堂上的“用户信息操作撤销”实例,使得系统可以实现多次撤销(可以使用HashMap、ArrayList等集合数......