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

最长公共上升子序列

时间:2023-10-05 10:23:23浏览次数:31  
标签:... 结尾 int 公共 序列 include 最长

题目概述:给定两个序列,求解它们的最长公共上升子序列
解题思路
集合定义:f[i][j]:所有a[1...i]中和b[1...j]中以b[j]结尾的最长上升子序列的长度。
集合划分:不包含a[i]:等价于所有a[1...i - 1]中和b[1...j]中以b[j]结尾的最长上升子序列的长度,即f[i][j] = f[i - 1][j];
包含ai:由集合定义可知,此时若成立,则a[i] = b[j].再根据倒数第二个数是以哪个数结尾进行再次划分,即
f[i][j] = max(f[i][j],f[i - 1][k]),k = 1,2,3...j-1.

暴力版\(O(n^3)\)
#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

const int N = 3010;

int f[N][N];//f[i][j]表示a[1..i]中和b[1...j]中以b[j]结尾的最长上升公共子序列(也可以以a[i]结尾)
int a[N],b[N];
int n;

int main(){
    
    cin >> n;
    
    for(int i = 1; i <= n; i ++)scanf("%d",&a[i]);
    for(int i = 1; i <= n; i ++)scanf("%d",&b[i]);
    
    for(int i = 1; i <= n;  i++)
        for(int j = 1; j <= n; j ++){
            //不包含a[i]
            f[i][j] = max(f[i][j],f[i - 1][j]);
            //包含a[i],前提a[i] == b[j]
            if(a[i] == b[j]){
                int maxv = 1;
                //根据倒数第二个数继续划分
                for(int k = 1; k < j; k ++){
                    //保证是上升子序列
                    if(b[k] < b[j])
                        maxv = max(maxv,f[i][k] + 1);
                }
                f[i][j] = max(f[i][j],maxv);
            }
        }
        
    int res = 0;
    for(int i = 1; i <= n; i ++)res = max(res,f[n][i]);
    
    cout << res << endl;
    
    return 0;
}

由于每次在再次划分时,都会存在大量重复枚举,可以对这部分进行优化,维护一个前缀最大值。

优化版\(O(n^2)\)
#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

const int N = 3010;

int f[N][N];//f[i][j]表示a[1..i]中和b[1...j]中以b[j]结尾的最长上升公共子序列(也可以以a[i]结尾)
int a[N],b[N];
int n;

int main(){
    
    cin >> n;
    
    for(int i = 1; i <= n; i ++)scanf("%d",&a[i]);
    for(int i = 1; i <= n; i ++)scanf("%d",&b[i]);
    
    for(int i = 1; i <= n;  i++){
        int maxv = 1;
        for(int j = 1; j <= n; j ++){
            //不包含a[i]
            f[i][j] = max(f[i][j],f[i - 1][j]);
            //包含a[i],前提a[i] == b[j]
            if(a[i] == b[j])f[i][j] = max(maxv,f[i][j]);
            if(b[j] < a[i])maxv = max(maxv,f[i - 1][j] + 1);
        }
    }
    int res = 0;
    for(int i = 1; i <= n; i ++)res = max(res,f[n][i]);
    
    cout << res << endl;
    
    return 0;
}

标签:...,结尾,int,公共,序列,include,最长
From: https://www.cnblogs.com/dengch/p/17742751.html

相关文章

  • 流畅的python笔记 (二) 2.序列构成的数组
    内置序列类型分类1:容器序列(能存放不同类型):list,tuple,collections.deque扁平序列(不能存放不同类型):str,bytes,bytearray,memoryview,array.array分类2:可变序列(能被修改):list,bytearray,array.array,collections.deque,memoryview不可变序列:tuple,str,bytes列表推导......
  • P2757 [国家集训队] 等差子序列
    P2757[国家集训队]等差子序列在线段树存哈希的时候,注意字符长度的改变,否则query会崩掉lolquery(intu,intl,intr,intlft,intrht){if(lft<=l&&r<=rht)returntr[u];else{intmid=(l+r)>>1;if(rht<=......
  • 根据先序序列和中序序列构造二叉树
    阅读本文之前希望读者可以先掌握如何根据先序序列和中序序列手动画出二叉树。所用二叉树数据结构如下:typedefstructTreeNode{ chardata; TreeNode*lchild,*rchild;}TreeNode,*Tree;该方法声明如下TreecreateTree(char*pre,intl1,intr1,char*in,intl2,intr2);......
  • 题解 [CSP-S 2021] 括号序列
    题目链接对于括号题,基本是栈匹配没有匹配的左括号和区间\(dp\)两个方向。这道题括号序列并不确定,只能用区间\(dp\)搞。如果直接设\(f_{l,r}\)表示\(l\simr\)的合法括号序列,那么由区间\(dp\)的套路可知,需要枚举中间点进行合并,那么\(()()()\)的情况就会出问题,原因是......
  • Prufer序列
    Prufer序列的转化方法见这篇博客(这篇文章里这道模板题的高精处理方法也看看)这里主要是对这篇博客的一些说明。首先:为什么Prufer序列与无根树一一对应?我们要先知道两个引理:出现在Prufer序列中的点一定是原无根树的非叶子节点,没有出现在Prufer序列中的一定是原无根树的叶子节点......
  • C 序列(seq)
    Day\(|\Sigma|\)。模拟赛里面的题,早上降智没调出来。题意大概就是求区间所有子区间的只出现在子区间内的数的最大值的和。记录一个数\(i\)的最左出现位置\(l_i\)和最右出现位置\(r_i\),一个数只在\([L,R]\)中出现当且仅当\([l_i,r_i]\subseteq[L,R]\)。考虑扫描线,统一......
  • 给PG数据库已有表,已存在列添加序列并设置序列当前值为自增列的最大值
    CREATEORREPLACEFUNCTION"public"."add_sequence_to_table"("p_table_name"text,"p_column_name"text)RETURNS"pg_catalog"."void"AS$BODY$DECLAREmax_valueINTEGER;sequence_nametext;B......
  • Leetcode 1143. 最长公共子序列
    https://leetcode.cn/problems/longest-common-subsequence/description/?envType=study-plan-v2&envId=top-100-liked给定两个字符串text1和text2,返回这两个字符串的最长公共子序列的长度。如果不存在公共子序列,返回0。一个字符串的子序列是指这样一个新的字符串:它......
  • 《Java编程思想第四版》学习笔记32--关于static字段的序列化
    //:CADState.java//Savingandrestoringthestateofa//pretendCADsystem.importjava.io.*;importjava.util.*;abstractclassShapeimplementsSerializable{publicstaticfinalintRED=1,BLUE=2,GREEN=3;privateintxPos,yPos,dimension;p......
  • 最大上升子序列和
    题目概述:给定一个序列,求解该序列的最大上升子序列的和解题思路:我们在LIS的集合定义为:以i结尾的上升子序列的最大长度,那其实我们只需要将集合定义改为:以i结尾的上升子序列的最大和即可。#include<iostream>#include<algorithm>#include<cstring>#include<set>#include<v......