14届蓝桥杯 C/C++ B组 T5 接龙排序 (最长上升子序列DP+优化)

不难发现这是一个LIS问题,但是如果直接套用LIS的模版,在数据范围到达 1 e 5 1e5 1e5 的情况下,就只能够得到一半的分数,所以我们需要对其进行优化。

首先给出暴力的代码:

cpp 复制代码
#include<iostream>
using namespace std;
const int N = 1e5+10;

string a[N];	//为了方便比较数的首尾,直接用string类型存
int f[N];

int main(){
	int n;cin >> n;
	for(int i = 1;i <= n;i++)cin >> a[i];

	for(int i = 1;i <= n;i++){
		f[i] = 1;
		for(int j = 1;j < i;j++){
			if(a[i][0] == a[j][a[j].length() - 1])
				f[i] = max(f[i],f[j] + 1);
		}
	}
	
	int res = 0;
	for(int i = 1;i <= n;i++)res = max(res,f[i]);

	cout << n - res;
	return 0;
}

那么如何优化,注意到暴力程序只有一个地方达到了两层的循环,所以我们只要优化掉一层循环即可。

那么如何优化以下代码:

复制代码
for(int j = 1;j < i;j++){
	if(a[i][0] == a[j][a[j].length() - 1])
		f[i] = max(f[i],f[j] + 1);
}

此处代码写出来是为了枚举比较首尾,那么如果我们能够直接定位和ai的首部相同尾部的子序列的长度不就不需要判断了吗。

所以使用一个数组来存尾部是 1 1 1 ~ 9 9 9 中某一个数结尾的接龙子序列的最长长度,在状态转移时直接省掉了判断的步骤。

优化代码:

cpp 复制代码
#include<iostream>
#include<map>
using namespace std;
const int N = 1e5 + 10;

string a[N];
map<char,int>m;
int f[N];

int main() {
    int n; cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> a[i];

    for (int i = 1; i <= n; i++) {
        f[i] = 1;
        f[i] = max(f[i],m[a[i][0]] + 1);
        m[a[i][a[i].length() - 1]] = max(f[i],m[a[i][a[i].length() - 1]]);//这里必须取max,因为f[i]不一定就更大
    }

    int res = 0;
    for(int i = 1;i <= n;i++)res = max(res,f[i]);
    cout << n - res;
    return 0;
}
相关推荐
Warren2Lynch36 分钟前
掌握 UML 构造型、标记定义与标记值:面向领域特定建模的 UML 扩展全面指南
大数据·算法·uml
157092511341 小时前
【无标题】
开发语言·python·算法
稚南城才子,乌衣巷风流1 小时前
换根法(Rerooting)算法详解
算法
晓子文集1 小时前
Tushare接口文档:期货交易日历(fut_trade_cal)
大数据·算法
王维同学2 小时前
Credential Provider、Filter 与 PLAP 的 CLSID 枚举
c++·windows·安全·注册表
Carlgood-Minecraft2 小时前
随机分位系统破解版 (BPS)Version-B4.2
c++
^yi2 小时前
【Linux系统编程】进程状态的理解
算法·僵尸进程·孤儿进程·进程状态·挂起状态·阻塞状态
hhzz3 小时前
机器学习-算法模型系列文章:04-KNN 不做标准化就跑KNN?你的模型正在被一个特征“独裁“
人工智能·算法·机器学习
冻柠檬飞冰走茶3 小时前
PTA基础编程题目集 7-7 12-24小时制(C语言实现)
c语言·开发语言·数据结构·算法
长不胖的路人甲3 小时前
二叉排序树(BST)Java 完整实现 + 删除思路详解
java·开发语言·算法