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

最长公共子序列

时间:2023-12-17 16:33:54浏览次数:23  
标签:mid len 公共 序列 最长 dp

最长公共子序列

一、什么是最长公共子序列(Longest Common Subsequence, LCS)?

最长公共子序列(LCS)是指在两个序列中,找出一个最长的子序列,使得这个子序列在这两个序列中都出现过。换句话说,就是从两个序列中删除一些元素后,剩下的最长公共子序列的长度。

二、原理

我们可以使用动态规划的方法来解决这个问题。首先,我们需要定义一个二维数组dp,其中dp[i][j]表示序列1的前i个元素和序列2的前j个元素的最长公共子序列的长度。接下来,我们可以通过以下步骤计算dp数组:

  1. 初始化dp数组的第一行和第一列为0。

  2. 从第二行第二列开始遍历dp数组,对于每个位置(i, j),如果序列1的第i个元素等于序列2的第j个元素,那么

     

    \[dp[i][j] = dp[i-1][j-1] + 1 \]
     
    
    否则,
    
     
    
    \[dp[i][j] = max(dp[i-1][j], dp[i][j-1]) \]
     

     

  3. 最后,dp[m][n]就是我们要求的最长公共子序列的长度,其中mn分别是序列1和序列2的长度。

三、C++代码实现

#include<bits/stdc++.h>
#define reg register
using namespace std;

// 定义一个函数read,用于读取输入的整数并返回
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-') f=-1; // 如果输入的是负号,则将f设为-1
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=(x<<1)+(x<<3)+(ch^48); // 将输入的数字转换为二进制表示,并存储在x中
        ch=getchar();
    }
    return x*f; // 返回读取的整数
}

// 定义一个函数write,用于输出整数x并在前面添加负号(如果x为负数)
void write(int x){
    if(x<0){
        putchar('-'); // 如果x为负数,先输出负号
        x=-x; // 将x变为正数
    }
    if(x>9) write(x/10); // 如果x大于9,递归调用write函数输出十位数
    putchar(x%10+'0'); // 输出个位数
    return ;
}

const int MAXN=100005,INF=0x7fffffff; // 定义常量MAXN为100005
int n,mapp[MAXN],dp[MAXN]; // 定义变量n、mapp[]、dp[]
vector<int > a,b; // 定义向量a、b

int main(){
    n=read(); // 从输入中读取整数n,存入变量n中
    a.push_back(0),b.push_back(0); // 在向量a和b的末尾分别添加元素0
    for(reg int i=1;i<=n;i++){a.push_back(read());mapp[a[i]]=i;} // 从输入中读取n个整数,存入向量a中,并将每个元素在向量a中的下标存入数组mapp中对应的位置
    for(reg int i=1;i<=n;i++){b.push_back(read());dp[i]=INF;} // 从输入中读取n个整数,存入向量b中,并将每个元素在dp[]中的值初始化为最大值
    for(reg int i=1;i<=n;i++) b[i]=mapp[b[i]]; // 将向量b中的每个元素替换为其在数组mapp中的下标所对应的值
    dp[1]=b[1]; // 将dp[1]设置为b[1]的值
    int len=1; // 将len设置为1
    for(reg int i=2;i<=n;i++){ // 从第2个元素开始遍历向量b和dp[]
        int l=0,r=len,mid; // 将l、r、mid分别初始化为0、len、len/2的商
        if(b[i]>dp[len]) dp[++len]=b[i]; // 如果b[i]大于dp[len],则将dp[len]更新为b[i]的值,并将len加1
        else{
            while(l<r){ // 当l小于r时,执行循环体
                mid=(l+r)>>1; // 将mid设置为l和r的平均值
                if(dp[mid]>b[i]) r=mid; // 如果dp[mid]大于b[i],则将r更新为mid的值
                else l=mid+1; // 否则将l更新为mid+1的值
            }
            dp[l]=min(b[i],dp[l]); // 将dp[l]更新为b[i]和dp[l]中的较小值
        }
    }
    write(len); // 将len写入输出流
    return 0; // 程序正常结束,返回0
}

 

四、例题及题解

题目:给定两个字符串序列 s1 和 s2,请编写一个函数 longestCommonSubsequenceLength,返回它们的最长公共子序列的长度。你只能使用一次回溯法。

解题思路:
由于题目要求只使用一次回溯法,我们可以先找到两个字符串的最长公共子序列,然后再根据最长公共子序列构造出原问题中的字符串。这样就可以避免使用递归。具体实现可以参考上面的 C++ 代码。

https://www.cnblogs.com/Nebulary/p/17620971.html    

标签:mid,len,公共,序列,最长,dp
From: https://www.cnblogs.com/liylllove/p/17909268.html

相关文章

  • 删除序列相同元素并保持顺序
    问题怎样在一个序列上面保持元素顺序的同时消除重复的值?解决方案如果序列上的值都是hashable类型,那么可以很简单的利用集合或者生成器来解决这个问题。比如:defdedupe(items):seen=set()foriteminitems:ifitemnotinseen:yielditemseen.add(item) 下面是使......
  • 3. 无重复字符的最长子串
    1.题目介绍给定一个字符串\(s\),请你找出其中不含有重复字符的 最长子串 的长度。示例 1:输入:s="abcabcbb"输出:3解释:因为无重复字符的最长子串是"abc",所以其长度为3。示例2:输入:s="bbbbb"输出:1解释:因为无重复字符的最长子串是"b",所以其长度为......
  • 数字信号处理-序列的抽取与插值
    0前言期中考好像就这里没考好呢,一看就是之前没好好听课没好好预习复习,到期中考也没弄懂这里(甚至发现作业题都忘记写了,那段时间忙比赛去了,真是得不偿失),所以才不会。1序列抽取序列的$D$抽取$x_d(n)=x(Dn)$,$D$为整数,叫抽取因子意义:每个连贯的D抽样中抽一个样值,从而减小数据量......
  • 基于LSTM模型的时间序列预测(车厢重量预测),Python中Keras库实现LSTM,实现预测未来未知数
    简介LSTM是一种常用的循环神经网络,其全称为“长短期记忆网络”(LongShort-TermMemoryNetwork)。相较于传统的循环神经网络,LSTM具有更好的长期记忆能力和更强的时间序列建模能力,因此在各种自然语言处理、语音识别、时间序列预测等任务中广泛应用。问题场景:对一节火车进行装载货物,......
  • P2516 [HAOI2010] 最长公共子序列
    求方案数,直接从\(f[i-1][j]\)和\(f[i][j-1]\)转移过来,如果\(s1[i]==s2[j]\)就加上\(f[i-1][j-1]\),如果\(s1[i]!=s2[j]\)且\(f[i][j]==f[i-1][j-1]\)说明两边转移到了\(f[i-1][j-1]\),减去重复部分\(f[i-1][j-1]\)就行了。比较好的理解方式是画个网格图,如果\(s1[......
  • 6、采集公共数据平台归集任务
    1、数据需求:采集当前配置任务及子任务的详细信息,页面请求返回数据是json格式。 #-*-coding:utf-8-*-#爬取公共数据平台数据归集任务importmathimportreimportpandasaspdimportrequests#初始化参数all_data=[]all_data2=[]defdirectory_list(cookie,......
  • 基因组序列比对(read alignment)
    基因组序列比对(readalignment)技术,是将测序得到的read与已有的参考基因组进行比对,找到read与参考基因组匹配的对应位置,继而得到序列比对的详细结果。由于参考基因组碱基数极多,测序得到的read数据量极大,且测序的DNA序列中存在各种碱基变异和测序错误,因此不能直接将read与参考基因......
  • asp.net core 使用newtonsoft完美序列化WebApi返回的ValueTuple
    https://www.cnblogs.com/kugar/p/12334210.html   由于开发功能的需要,又懒得新建太多的class,所以ValueTuple是个比较好的偷懒方法,但是,由于WebApi需要返回序列化后的json,默认的序列化只能将ValueTuple定义的各个属性序列化成Item1...n  但是微软还是良心的为序列......
  • 128. 最长连续序列
    1.题目介绍给定一个未排序的整数数组\(nums\),找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。请你设计并实现时间复杂度为 \(O(n)\)的算法解决此问题。示例1:输入:nums=[100,4,200,1,3,2]输出:4解释:最长数字连续序列是[1,2,3,4]。它的长度为4。示例......
  • Hadoop 数据类型及序列化
    1.Hadoop数据类型Java类型HadoopWritable类型BooleanBooleanWritableWritableWritableWritableWritableWritableWritableWritableWritableWritable2.为何Hadoop有自身序列化与反序列化Java自身的序列化除去本身Bean的数据......