首页 > 其他分享 >最长公共子序列问题

最长公共子序列问题

时间:2022-11-09 00:23:21浏览次数:33  
标签:show int len 公共 序列 100 最长 dis

最长公共子序列和最长公共子串区别

最长公共子串(Longest Common Substring)与最长公共子序列(Longest Common Subsequence)的区别:

子串要求在原字符串中是连续的,而子序列则只需保持相对顺序一致,并不要求连续。

例如  X = {a, Q, 1, 1}; Y = {a, 1, 1, d, f}

那么,{a, 1, 1}是X和Y的最长公共子序列,但不是它们的最长公共字串。

最优子结构

 

 

 思路

我们的目的是寻找两个顺序相对一致的序列

所以我们需要构建一个二维数组进行统计,记录遍历的时候他们相同的地方

设有这样的两个序列:

{A,L,C,H,E,M,I,S,T}

{A,L,G,O,R,I,T,H,M,S}

 

 

 第一行的意思可以看作空和空.空和A。。。的最长子序列都为0

 从第二行开始,如果相同就将左上角的值复制加一填入,所以这里就填上   1(0+1)

 

 

 到第三个,元素不同的话就将这个位置的元素比较填入最大的,这里上是0左是1,所以填入1;

 

 

 以此类推

到了第二行,第二行与第二列元素一样,就读取左上角元素的复制后加一填入,1加1填入2

 

 

 之后都是以此类推,最后得到了

 

 

 通过以上的分解后,我们可以得到这样一个状态转移方程

if(a===b){ //如果他们相同
table[row][col] = table[row - 1][co1 - 1] + 1; //我们找到他斜上角的那个值进行加一之后赋值
} else {
table[row][col] = Math. max(table[row][col - 1], table[row - 1][col]);//如果不相同,我们就填入元素上方和左边最大的元素
}

 

整理后的代码为


#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int len[100][100]; //最大子序列的生成矩阵
int dis[100][100]; //创建数组dis[][]来储存每一次的信息,如果xi=yj则为1,另外两种情况为dis[][]中储存为2,3;如1代表两个都是,2代表行是左,3代表列是上
char A[100] = "ABCBDAB";
char B[100] = "BDCABA";
void show(int, int);


int main()
{
int n = strlen(A);
int m = strlen(B);
printf("%d %d\n", n, m);//输出两个序列的长度


int i, j, k;
for (i = 0; i <= n; i++)
  len[i][0] = 0;  //让列为0
for (i = 0; i <= m; i++)
  len[0][i] = 0;  //让第一行为0

for (i = 1; i <= n; i++){

  for (j = 1; j <= m; j++){

    if (A[i-1] == B[j-1]){ //若他们相等,则让他等于左上角的元素加1
      len[i][j] = len[i - 1][j - 1] + 1;
      dis[i][j] = 1;      //记录下来在这里是相等的,标记为1
    }
    else if (len[i - 1][j] >= len[i][j - 1]){ //他们不相等的时候,取上和左元素最大的那个
      len[i][j] = len[i - 1][j];  
      dis[i][j] = 3;  //取上标记为3
    }else{
      len[i][j] = len[i][j - 1];
      dis[i][j] = 2;  //取左标记为2
    }
  }
}
printf("最大子序列长度:%d ", len[n][m]); //最后的一个按直接的结果,他的值就是最长的序列数

 

for (i = 0; i <= n; i++){
  for (j = 0; j <= m; j++){
    printf("%d ", dis[i][j]);
}
puts("");
}
puts("子序列为:");


show(n, m);
}

void show(int i, int j){

  if (i == 0 || j == 0)

    return;

  if (dis[i][j] == 1){

    show(i - 1, j - 1);

    printf("%c ", A[i-1]);
  }
  else if (dis[i][j] == 3){
    show(i - 1, j);
  }else{
    show(i, j - 1);
  }
}

 

 

标签:show,int,len,公共,序列,100,最长,dis
From: https://www.cnblogs.com/kuailest/p/16871777.html

相关文章

  • 【Javaweb】implements Serializable是什么意思?反序列化是什么意思?
    为了保证数据传输的可靠性,常常要implementsSerializable,为什么?对象本质上是虚无缥缈的,只是内存中的一个地址,如果想要让对象持久化,让对象在网络上传输,总不可能传送一个内......
  • 基于VUEX的公共存储器store的快速上手流程
    vuex的快速安装与使用​​store公共存储器​​​​state.js添加数据元​​​​mutations.js创建一个方法​​​​在组件中提交:​​​​在组件中使用:​​store公共存储器在使......
  • P4555 最长双回文串 解题报告
    看到回文串,于是就想到了马拉车。马拉车可以帮我们求出每个\(i\)的最大扩展距离,容易得出,双回文串就是两个回文串拼一起。当然,两个回文串必须要相交,不然形不成一个字符串......
  • AcWing 896.最长上升子序列Ⅱ
    题目链接:http://www.acwing.com/problem/content/898/不像是dp,更像是贪心相对于数据小的上升子序列问题,此题用过的二分后的时间复杂度为nlogn。在本题中首先需要明白:......
  • P3379 【模板】最近公共祖先(LCA)tarjan算法
    tarjan算法求LCA//tarjan算法#include<bits/stdc++.h>usingnamespacestd;constintmaxn=5e5+10;vector<int>tre[maxn];structnode{ intto; intid;};vect......
  • 最长有效括号
    题目给你一个只包含'(' 和')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。示例1:输入:s="(()"输出:2解释:最长有效括号子串是"()"示例2:输入:s=")()......
  • 序列化与反序列化
    序列化与反序列化序列化的意思是将一种格式的数据按照某种规则转成相应等效的另一种格式的数据。反序列化是相反的过程。一般可将数据序列化为二进制格式。也可序列化为其它......
  • 恒创科技:私有云和公共云企业选择哪个更好?
    私有云和公共云企业选择哪个更好?为确保您的业务确实从云中受益,选择正确的云计算模型很重要。您的应用程序和数据的性质将真正决定哪种云模型最适合您。对于任务关键型......
  • 问题 N: 零基础学C/C++159——最长字符串
    题目一点也不难哦,就是要学会二维数组的输入输出但是不知为何这题有一个很奇怪的坑,如果你是AC:83%那么恭喜你掉坑里了!!这道题目竟然有一个检测点在最后的时候加\n确实......
  • 学习笔记-PHP的反序列化
    魔术方法方法名调用条件__call调用不可访问或不存在的方法时被调用__callStatic调用不可访问或不存在的静态方法时被调用__clone进行对象clone时被调用......