最长公共上升子序列(LCIS)

2023-11-17

前置知识

  1. LCS
    在这里插入图片描述

  2. LIS

注意:

  刚开始看这个问题的时候,第一反应是先求出LCS再求出LCS的LIS,事实上这是有问题的,我们并不能保证这么求出的LCIS是最长的,比如下面这个例子

Example
a:7 1 5 6 4 2 7
b:7 1 5 4 6 7 2
按照递归的取“最长公共子序列”,取出:
7 1 5 6 2
此序列的“最长上升子序列”为:
1 5 6 (len=3)
但原序列的“最长公共上升子序列”为:
1 5 6 7 (len=4)

求解

 设第一个串为a,第二个串为b

  1. 首先确定dp状态f[i, j],表示前a串前i个字符和b串前j个字符且以b[j]为结尾的LCIS
  2. 状态方程:
    对于当处于(a[i], b[j]) 状态时 ,由于dp状态就决定了,b[j]是一定作为这个状态下LICS的结尾的,所以对于a[i],就有两种情况,将其纳入LCIS或者不纳入,首先先说不讲a[i]纳入LCIS的情况
    (1)若是 a[i] != b[j] ,显然是一定不能讲a[i]与b[j]进行配对的,那么问题就缩小成了前a的前i - 1个字符与b的前j个字符且以b[j]结尾的LCIS,即f[i - 1, j]也就是说 ,i之前的以b[j]结尾的序列自然没有改变,仍然是长度仍然是f[i−1][j]; 若是a[i] == b[i] 如果不想要a[i]与b[j]进行配对,是不是也会得到上面的结果,故当
    不讲a[i]与b[j]配对(或无法配对)时,f[i, j] = f[i - 1, j]

(2)当a[i] == b[j]且它们进行配对时,就要在a串前i - 1个字符和b的前j - 1个字符中找到一个最长的序列,设这个序列以t结尾且b[t] < b[j],是不是就等价于
f[i, j] = max(f[i - 1, t]) + 1 (t > 0 && t < j && b[t] < b[j])

这样就把这个问题可以转化为最优子结构的问题,且得到状态转移方程如下

				f[i - 1, j]    (a[i] != b[j])
f[i, j] = 
				max(f[i - 1, t]) + 1   (t > 0 && t < j && b[t] < b[j]) (a[i] == b[j])

讲上述思路转化为代码

for (int i = 1; i <= n; i ++ )
{
    for (int j = 1; j <= n; j ++ )
    {
        f[i][j] = f[i - 1][j];
        if (a[i] == b[j])
        {
            int maxv = 1;
            for (int k = 1; k < j; k ++ )
                if (b[j] > b[k])
                    maxv = max(maxv, f[i - 1][k] + 1);
            f[i][j] = max(f[i][j], maxv);
        }
    }
}

 上面代码的时间复杂度为O(n 3),是很不理想的,可以对其进行等价转化为O(n 2)的优化
观察第三层循环,可以发现每次循环求得的maxv是满足a[i] > b[k]的f[i - 1][k] + 1的前缀最大值。,而且是在a[i] == b[j]的时候成立,且可以发现,在每一次进行第二层循环时,a[i]是不变的,这也就可以推出,与a[i]进行配对的b[j]的值也是暂时不变的,那么把b[j]等价转化为a[i],并将maxv提至第一层循环内,在每一次比较a[i]和b[j]时,一起讲maxv处理出来,这样就可以将其优化为如下的O(n 2)的代码

for (int i = 1; i <= n; i++) {
        int maxv = 0;
        for (int j = 1; j <= n; j++) {
            f[i][j] = f[i - 1][j];
            if (a[i] == b[j]) f[i][j] = max(f[i][j], maxv + 1);
            if (a[i] > b[j]) maxv = max(maxv, f[i - 1][j]);        
        }
}

这样其实已经够了,但是追求优化的话,还可以进行空间的优化,不难发现,每一次都止利用了上一层的结果,那么可以采用滚动数组的方法进行空间优化

for (int i = 1; i <= n; i++) {
        int maxv = 0;
        for (int j = 1; j <= n; j++) {
            if (a[i] == b[j]) f[j] = max(f[j], maxv + 1);
            if (a[i] > b[j]) maxv = max(maxv, f[j]);        
        }
    }

acwing 272 最长公共上升子序列

#include <iostream>

using namespace std;

const int maxn = 3e3 + 5;

int f[maxn], a[maxn], b[maxn];
int n, ans;

int main()
{
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> a[i];
    for (int i = 1; i <= n; i++) cin >> b[i];
    for (int i = 1; i <= n; i++) {
        int maxv = 0;
        for (int j = 1; j <= n; j++) {
            if (a[i] == b[j]) f[j] = max(f[j], maxv + 1);
            if (a[i] > b[j]) maxv = max(maxv, f[j]);        
            ans = max(f[j], ans);
        }
    }
    cout << ans << endl;
    return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

最长公共上升子序列(LCIS) 的相关文章

  • WCF RIA 服务 - 加载多个实体

    我正在寻找一种模式来解决以下问题 我认为这很常见 我正在使用 WCF RIA 服务在初始加载时将多个实体返回给客户端 我希望两个实体异步加载 以免锁定 UI 并且我想利用 RIA 服务来执行此操作 我的解决方案如下 似乎有效 这种方法会遇到
  • 为什么两个不同的 Base64 字符串的转换会返回相等的字节数组?

    我想知道为什么从 base64 字符串转换会为不同的字符串返回相同的字节数组 const string s1 dg const string s2 dq byte a1 Convert FromBase64String s1 byte a2
  • 动态加载程序集的应用程序配置

    我正在尝试将模块动态加载到我的应用程序中 但我想为每个模块指定单独的 app config 文件 假设我的主应用程序有以下 app config 设置
  • 类模板参数推导 - clang 和 gcc 不同

    下面的代码使用 gcc 编译 但不使用 clang 编译 https godbolt org z ttqGuL template
  • BitTorrent 追踪器宣布问题

    我花了一点业余时间编写 BitTorrent 客户端 主要是出于好奇 但部分是出于提高我的 C 技能的愿望 我一直在使用理论维基 http wiki theory org BitTorrentSpecification作为我的向导 我已经建
  • 用于登录 .NET 的堆栈跟踪

    我编写了一个 logger exceptionfactory 模块 它使用 System Diagnostics StackTrace 从调用方法及其声明类型中获取属性 但我注意到 如果我在 Visual Studio 之外以发布模式运行代
  • 在 Windows 窗体中保存带有 Alpha 通道的单色位图会保存不同(错误)的颜色

    在 C NET 2 0 Windows 窗体 Visual Studio Express 2010 中 我保存由相同颜色组成的图像 Bitmap bitmap new Bitmap width height PixelFormat Form
  • HTTPWebResponse 响应字符串被截断

    应用程序正在与 REST 服务通信 Fiddler 显示作为 Apps 响应传入的完整良好 XML 响应 该应用程序位于法属波利尼西亚 在新西兰也有一个相同的副本 因此主要嫌疑人似乎在编码 但我们已经检查过 但空手而归 查看流读取器的输出字
  • 关于 C++ 转换:参数 1 从“[some_class]”到“[some_class]&”没有已知的转换

    我正在研究 C 并且遇到了一个错误 我不知道确切的原因 我已经找到了解决方案 但仍然想知道原因 class Base public void something Base b int main Base b b something Base
  • 不同枚举类型的范围和可转换性

    在什么条件下可以从一种枚举类型转换为另一种枚举类型 让我们考虑以下代码 include
  • 使用 Bearer Token 访问 IdentityServer4 上受保护的 API

    我试图寻找此问题的解决方案 但尚未找到正确的搜索文本 我的问题是 如何配置我的 IdentityServer 以便它也可以接受 授权带有 BearerTokens 的 Api 请求 我已经配置并运行了 IdentityServer4 我还在
  • while 循环中的 scanf

    在这段代码中 scanf只工作一次 我究竟做错了什么 include
  • 什么时候虚拟继承是一个好的设计? [复制]

    这个问题在这里已经有答案了 EDIT3 请务必在回答之前清楚地了解我要问的内容 有 EDIT2 和很多评论 有 或曾经 有很多答案清楚地表明了对问题的误解 我知道这也是我的错 对此感到抱歉 嗨 我查看了有关虚拟继承的问题 class B p
  • 如何查看网络连接状态是否发生变化?

    我正在编写一个应用程序 用于检查计算机是否连接到某个特定网络 并为我们的用户带来一些魔力 该应用程序将在后台运行并执行检查是否用户请求 托盘中的菜单 我还希望应用程序能够自动检查用户是否从有线更改为无线 或者断开连接并连接到新网络 并执行魔
  • 通过指向其基址的指针删除 POD 对象是否安全?

    事实上 我正在考虑那些微不足道的可破坏物体 而不仅仅是POD http en wikipedia org wiki Plain old data structure 我不确定 POD 是否可以有基类 当我读到这个解释时is triviall
  • 将控制台重定向到 .NET 程序中的字符串

    如何重定向写入控制台的任何内容以写入字符串 对于您自己的流程 Console SetOut http msdn microsoft com en us library system console setout aspx并将其重定向到构建在
  • 基于 OpenCV 边缘的物体检测 C++

    我有一个应用程序 我必须检测场景中某些项目的存在 这些项目可以旋转并稍微缩放 更大或更小 我尝试过使用关键点检测器 但它们不够快且不够准确 因此 我决定首先使用 Canny 或更快的边缘检测算法 检测模板和搜索区域中的边缘 然后匹配边缘以查
  • C# 模拟VolumeMute按下

    我得到以下代码来模拟音量静音按键 DllImport coredll dll SetLastError true static extern void keybd event byte bVk byte bScan int dwFlags
  • 哪种 C 数据类型可以表示 40 位二进制数?

    我需要表示一个40位的二进制数 应该使用哪种 C 数据类型来处理这个问题 如果您使用的是 C99 或 C11 兼容编译器 则使用int least64 t以获得最大的兼容性 或者 如果您想要无符号类型 uint least64 t 这些都定
  • Windows 和 Linux 上的线程

    我在互联网上看到过在 Windows 上使用 C 制作多线程应用程序的教程 以及在 Linux 上执行相同操作的其他教程 但不能同时用于两者 是否存在即使在 Linux 或 Windows 上编译也能工作的函数 您需要使用一个包含两者的实现

随机推荐

  • 网络编程——TCP并发服务器模型

    1 多线程中的newfd 能否修改成全局 不行 为什么 因为如果是全局变量 文件描述符就是唯一的 所有的客户端都会在同一个文件描述符通信 2 多线程中分支线程的newfd能否不另存 直接用指针间接访问主线程中的newfd 不行 为什么 如果
  • 微信小程序-仿智行火车票12306

    微信小程序 仿智行火车票12306 微信小程序 仿智行火车票12306 主页有轮播图 有导航栏 有个人中心 可以实现火车票 飞机票 汽车票的选择 适合初学者学习 下面是示例图片 下载链接 https download csdn net do
  • Linux系统图形界面和命令行界面之间的切换

    一 系统不在虚拟机中的情况 使用ctrl alt F1 6切换到命令行界面 ctrl alt F7切换到图形界面 二 系统在虚拟机中的情况 Ctrl Alt shift F1 6切换到命令行界面 使用Alt F7返回到图形界面 注 以上方法
  • hashmap中为什么使用红黑树?

    在回答这个问题之前 我们先了解一下有关二叉树的基本内容 二叉排序树 又称二叉查找树 1 若左子树不为空 则左子树上所有结点的值均小于根结点的值 2 若右子树不为空 则右子树上所有结点的值均大于根节点的值 3 左右子树也为二叉排序树 平衡二叉
  • 2017 ICCV之语义分割:Cascaded Feature Network for Semantic Segmentation of RGB-D Images

    Cascaded Feature Network for Semantic Segmentation of RGB D Images 目前的问题 1 为了计算对象 场景关系的表示 最近大量的分割网络使用一组感受野来丰富卷积特征的文本信息 这
  • book_read_link

    结构性改革 黄奇帆 微信读书 分析与思考 黄奇帆的复旦经济课 黄奇帆 微信读书
  • java通过web3j获取ETH交易明细

    我们在项目里面如果想要得到用户的ETH交易明细怎么做呢 有两种方式 1 直接获取ETH最新块的交易明细 2 通过块获取用户的交易明细 废话不多说 直接贴代码看了 package com example demo web3jLog impor
  • pdf.js引入方式及初始化配置

    官方下载地址 Getting StartedA general purpose web standards based platform for parsing and rendering PDFs http mozilla github
  • actuator--基础--04--Springboot集成

    actuator 基础 04 Springboot集成 代码位置 https gitee com DanShenGuiZu learnDemo tree master actuator learn actuator01 1 代码 1 1 依
  • MongoDB游标

    数据库会使用游标返回 find 的执行结果 游标的客户端实现通常能够在很大程度上对查询的最终输出进行控制 你可以限制结果的数量 跳过一些结果 按任意方向的任意键组合对结果进行排序 以及执行许多其他功能强大的操作 要使用 shell 创建游标
  • 爬虫实战之华为应用市场

    目录 一 需求说明 二 步骤 1 检查当前页面的URL所获得的响应的数据 笨办法 程序验证 不建议 简单办法 抓包 验证 抓包 推荐 动态加载验证 查找页面的信息 2 获取排行页面数据 操作 源码 信息解析 3 详情页面分析 寻找URL 验
  • leetcode 577

    给定一个字符串 s 你需要反转字符串中每个单词的字符顺序 同时仍保留空格和单词的初始顺序 示例 1 输入 s Let s take LeetCode contest 输出 s teL ekat edoCteeL tsetnoc 示例 2 输
  • C++中的强引用与弱引用

    https juejin cn post 7102838307062546445 1 weak ptr的原理 weak ptr 是为了配合 shared ptr 而引入的一种智能指针 它指向一个由 shared ptr 管理的对象而不影响所
  • 神经网络中的激活函数

    一 激活的概念 将输入映射为特定分布的输出 完成非线性变换 多细胞生物神经元的树突接收信息 触发区整合电位 产生神经冲动 末端的突触向下一个神经元传递刺激 以人脑为例 人脑的细胞受刺激产生活动 而刺激的强度需要达到一定的阈值 没有达到阈值的
  • 基于51单片机数字频率计的设计与实现

    目录 第一章 系统原理与总体设计 1 1系统组成 1 2系统原理 1 3测量原理 1 4频率测量与总体设计 第二章 硬件电路设计 2 1硬件电路框图 2 2数字频率计原理图 2 3硬件电路设计 第三章 软件程序设计 3 1程序流程图 3 2
  • 魔方机器人之下位机编程------下位机完整程序

    头文件包含 include Includes h 总头文件 在此添加全局变量定义 uint8 msg 14 Hello World void PWM Init void PWM0 上侧旋转舵机 PWME PWME0 0x00 Disable
  • 查找恢复密钥

    登陆自己的微软账号可查看恢复密钥 点击以下链接查找恢复密钥 https account microsoft com devices recoverykey 根据密钥ID 输入对应的恢复密钥
  • win10蓝牙无法连接,可以尝试在此Windows设备上打开蓝牙

    win10蓝牙无法连接 可以尝试在此Windows设备上打开蓝牙 笔记本右下角蓝牙图标消失不见 操作步骤 1 首先在打开电脑中 按下 Win R 打开运行窗口输入 services msc 并进入 2 2 打开服务列表后 不断的向下翻 找到
  • 【华为OD机试真题】对称字符串(python)100%通过率 超详细代码注释 代码解读

    华为OD机试真题 2022 2023 真题目录 点这里 华为OD机试真题 信号发射和接收 试读 点这里 华为OD机试真题 租车骑绿道 试读 点这里 对称字符串 时间限制 1s空间限制 256MB限定语言 不限 题目描述 对称就是最大的美学
  • 最长公共上升子序列(LCIS)

    前置知识 LCS LIS 注意 刚开始看这个问题的时候 第一反应是先求出LCS再求出LCS的LIS 事实上这是有问题的 我们并不能保证这么求出的LCIS是最长的 比如下面这个例子 Example a 7 1 5 6 4 2 7 b 7 1