[GESP202509 六级] 划分字符串(含视频)

视频讲解:GESP202509 六级 划分字符串-信息学奥赛GESP等级考试真题解析

一、原题

题目描述

小 A 有一个由 n 个小写字母组成的字符串 s。他希望将 s 划分为若干个子串,使得子串中每个字母至多出现一次。例如,对于字符串 street 来说,str + e + e + t 是满足条件的划分;而 s + tree + t 不是,因为子串 tree 中 e 出现了两次。

额外地,小 A 还给出了价值 a1​,a2​,...,an​,表示划分后长度为 i 的子串价值为 ai​。小 A 希望最大化划分后得到的子串价值之和。你能帮他求出划分后子串价值之和的最大值吗?

输入格式

第一行,一个正整数 n,表示字符串的长度。

第二行,一个包含 n 个小写字母的字符串 s。

第三行,n 个正整数 a1​,a2​,...,an​,表示不同长度的子串价值。

输出格式

一行,一个整数,表示划分后子串价值之和的最大值。

输入输出样例

输入 #1

复制代码
6
street
2 1 7 4 3 3

输出 #1

复制代码
13

输入 #2

复制代码
8
blossoms
1 1 2 3 5 8 13 21

输出 #2

复制代码
8

说明/提示

对于 40% 的测试点,保证 1≤n≤10^3。

对于所有测试点,保证 1≤n≤10^5,1≤ai​≤10^9。

二、做题思路

1)填充数据

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	//1)填充数据
	//1.1)确定长度n
	int n;cin>>n; 
	//1.2)填充字符串s
	string s;cin>>s;
	//1.3)填充每种长度的价值 
	int a[100005]={};
	for(int i=1;i<=n;i++) cin>>a[i];
	return 0; 
}

2)动态规划:计算加入当前字符的最优解

2.1)初始化dp

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	//1)填充数据
	//....
	//2)动态规划:计算加入当前字符的最优解
	//2.1)初始化dp
	long long dp[100005]={};
	return 0; 
}

2.2)加入每个字符

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	//1)填充数据
	//....
	//2)动态规划:计算加入当前字符的最优解
	//2.1)初始化dp
	long long dp[100005]={};
	//2.2)加入每个字符
	for(int i=1;i<=n;i++){
		s[i-1]
	}
	return 0; 
}

2.3)不断和之前字符组合,计算最优解

2.3.1-2)计算起点(需字母不重复),起点=max(之前起点,当前字符出现次数+1)

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	//1)填充数据
	//....
	//2)动态规划:计算加入当前字符的最优解
	//2.1)初始化dp
	long long dp[100005]={};
	//2.2)加入每个字符
	int now=1;
	int word[26]={};
	for(int i=1;i<=n;i++){
		//2.3)不断和之前字符组合,计算最优解
		//2.3.1)计算组合起点max(之前起点,之前字符出现位置+1) 
		now=max(now,word[s[i-1]-'a']+1);
		//2.3.2)标记该字符最新出现位置 
		word[s[i-1]-'a']=i;
	}
	return 0; 
}

2.3.3)获取最优解=max(不拿,拿)

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	//1)填充数据
	//....
	//2)动态规划:计算加入当前字符的最优解
	//2.1)初始化dp
	long long dp[100005]={};
	//2.2)加入每个字符
	int now=1;
	int word[26]={};
	for(int i=1;i<=n;i++){
		//2.3)不断和之前字符组合,计算最优解
		//2.3.1)计算组合起点max(之前起点,之前字符出现位置+1) 
		now=max(now,word[s[i-1]-'a']+1);
		//2.3.3)获取最优解
		for(int j=i;j>=now;j--){
			//最优解=max(不拿,拿) 
			//不拿:dp[i]
			//拿:当前长度价值 + 之前的最优解
			//      a[i-j+1] +  dp[j-1]
			dp[i]=max(dp[i],a[i-j+1] +  dp[j-1]) ;
		}
		//2.3.2)标记该字符最新出现位置 
		word[s[i-1]-'a']=i;
	}
	return 0; 
}

三、答案

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	//1)填充数据
	//....
	//2)动态规划:计算加入当前字符的最优解
	//2.1)初始化dp
	long long dp[100005]={};
	//2.2)加入每个字符
	int now=1;
	int word[26]={};
	for(int i=1;i<=n;i++){
		//2.3)不断和之前字符组合,计算最优解
		//2.3.1)计算组合起点max(之前起点,之前字符出现位置+1) 
		now=max(now,word[s[i-1]-'a']+1);
		//2.3.3)获取最优解
		for(int j=i;j>=now;j--){
			//最优解=max(不拿,拿) 
			//不拿:dp[i]
			//拿:当前长度价值 + 之前的最优解
			//      a[i-j+1] +  dp[j-1]
			dp[i]=max(dp[i],a[i-j+1] +  dp[j-1]) ;
		}
		//2.3.2)标记该字符最新出现位置 
		word[s[i-1]-'a']=i;
	}
	//3)输出结果
	cout<<dp[n];
	return 0; 
}
相关推荐
小郎君65819 分钟前
Vue 多标签页的加载态设计:为什么我没有用 Suspense 实现 PageLoading
vue.js·算法
JJJennie7771 小时前
MAI Gateway私有化部署全攻略:大模型网关如何接入?附架构图
算法·gateway·ai网关·魔芋ai
東隅已逝,桑榆非晚1 小时前
算法3.双指针法-快乐数
c++·笔记·学习·算法
专注仿真1 小时前
卷积神经网络(CNN)算法详解
人工智能·python·算法·代码·大模型训练
FII工业富联科技服务1 小时前
多智能体如何进入制造现场?从业务协同到数字孪生验证
大数据·人工智能·算法·机器人·制造·数字孪生
≮傷£≯√1 小时前
httpserver_QNetWorkClient
算法
Evand J1 小时前
【PMSM例程11】永磁同步电机(PMSM)基于UKF的转速与转子位置估计。附下载链接
算法·matlab·卡尔曼滤波·永磁同步电机·ukf·pmsm·位置估计
货拉拉技术1 小时前
记忆即智能:重构对话式AI Agent认知基座的四层渐进式记忆与自进化系统
人工智能·算法
杜 硕2 小时前
从零开始的C++生活——第六讲——02
c++·算法·生活
小超人诞生日记2 小时前
C++ STL 反向迭代器:从源码框架到适配器实现
c++·算法