最长上升子序列 LIS

部署运行你感兴趣的模型镜像
题目:

http://acm.nyist.net/JudgeOnline/problem.php?pid=17

http://poj.org/problem?id=2533

两道题几乎一样,只不过对于输入输出的要求有所不同罢了。

LIS有两种方法:

一、第一种方法 · 时间复杂度为O(n^2):

状态:dp[i] := 区间为0~i的序列的LIS

转移方程:dp[i] = max(1, dp[k] + 1)  (0<=k<i && s[k]<s[i])

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string> 
using namespace std;

char s[10005];
int dp[10005];

int main ()
{
    int n;
    scanf("%d", &n);
    while(n--) {
        scanf("%s", &s);
        int len = strlen(s);
        for(int i=0; i<len; i++) {
            dp[i] = 1;
            for(int j=0; j<i; j++) {
                if(s[j] < s[i]) {
                    dp[i] = max(dp[i], dp[j]+1);
                }
            }
        }
        int ans = 0;
        for(int i=0; i<len; i++)    ans = max(ans, dp[i]);
        printf("%d\n", ans);
    }
    
    return 0;
}

 
二、第二种方法 · 时间复杂度为O(nlgn):

这种方法需要用二分查找查询到当前这一位元素应该是长度为多少的上升子序列的最后一位。

状态定义:dp[i] := 长度为i的上升子序列的当前最小的末尾元素,这里之所以要找最小的末尾元素,是因为越小越容易在后面加上一个稍大的元素使得找到的LIS更长!换句话说,倘若我已经将末尾元素的值设置为最低,尽力减小后来者的“门槛”了,但长度仍然只有这么多,那么上升子序列的最长长度也就只能是这样了。

举个例子:序列S为{1,4,2}

step1:将数组dp初始化为{+∞,+∞,+∞}

step2:开始遍历序列S

  ① 当前遍历到的元素为1时,我们在dp序列进行二分查找,寻找第一个大于等于1的元素的下标,我们找到dp[1]=+∞是第一个大于1的元素(dp的下标从1开始),于是dp[1]=1,即:目前来看,长度为1的上升子序列的末尾元素为1

  ② 当前遍历到的元素为4时,在dp序列中找到第一个大于等于4的元素为dp[2]=+∞,所以dp[2]=4。这时,dp={1,4,+∞,+∞},说明长度为1和2的上升子序列的最小末尾元素都已经找到。

  ③ 当前遍历到的元素为2时,在dp序列中找到第一个大于等于2的元素为dp[2]=4,这说明元素2没有办法让目前的最长上升序列更长(除非>4),但是相对于它后面的元素而言,它更有“潜质”作为长度为2的上升子序列的末尾元素,因为它比当前的4要小,4能做到的它都可以,而且可能得到比4更长的上升序列,即做得还可能比4要好。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string> 
#include <algorithm>
#define INF 30
using namespace std;

char s[10005];
int dp[10005];

int main ()
{
    int n;
    scanf("%d", &n);
    while(n--) {
        scanf("%s", &s);
        int len = strlen(s);
        for(int i=0; i<len; i++) {
            dp[i] = INF;
        } 
        for(int i=0; i<len; i++) {
            *lower_bound(dp, dp+len, s[i]-'a') = s[i]-'a';
        }
        printf("%d\n", lower_bound(dp, dp+len, INF) - dp);
    }
    
    return 0;
}

您可能感兴趣的与本文相关的镜像

EmotiVoice

EmotiVoice

AI应用

EmotiVoice是由网易有道AI算法团队开源的一块国产TTS语音合成引擎,支持中英文双语,包含2000多种不同的音色,以及特色的情感合成功能,支持合成包含快乐、兴奋、悲伤、愤怒等广泛情感的语音。

内容概要:本文详细介绍了“秒杀商城”微服务架构的设计与实战全过程,涵盖系统从需求分析、服务拆分、技术选型到核心功能开发、分布式事务处理、容器化部署及监控链路追踪的完整流程。重点解决了高并发场景下的超卖问题,采用Redis预减库存、消息队列削峰、数据库乐观锁等手段保障数据一致性,并通过Nacos实现服务注册发现与配置管理,利用Seata处理跨服务分布式事务,结合RabbitMQ实现异步下单,提升系统吞吐能力。同时,项目支持Docker Compose快速部署和Kubernetes生产级编排,集成Sleuth+Zipkin链路追踪与Prometheus+Grafana监控体系,构建可观测性强的微服务系统。; 适合人群:具备Java基础和Spring Boot开发经验,熟悉微服务基本概念的中高级研发人员,尤其是希望深入理解高并发系统设计、分布式事务、服务治理等核心技术的开发者;适合工作2-5年、有志于转型微服务或提升架构能力的工程师; 使用场景及目标:①学习如何基于Spring Cloud Alibaba构建完整的微服务项目;②掌握秒杀场景下高并发、超卖控制、异步化、削峰填谷等关键技术方案;③实践分布式事务(Seata)、服务熔断降级、链路追踪、统一配置中心等企业级中间件的应用;④完成从本地开发到容器化部署的全流程落地; 阅读建议:建议按照文档提供的七个阶段循序渐进地动手实践,重点关注秒杀流程设计、服务间通信机制、分布式事务实现和系统性能优化部分,结合代码调试与监控工具深入理解各组件协作原理,真正掌握高并发微服务系统的构建能力。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值