专栏文章
题解:P14075 [GESP202509 六级] 划分字符串
P14075题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @minrfmax
- 此快照首次捕获于
- 2025/12/02 07:08 3 个月前
- 此快照最后确认于
- 2025/12/02 07:08 3 个月前
前传
六级考生一枚,考场上没调出来,准备下一次了。结果发现推导公式推错了。
思路
根据题目中给出的“价值之和的最大值”,我们可以判断这是一个动态规划;题目中给出了关键信息 ,代表的是把字串划分为 长度可以得到 分。
数组的定义
我们定义 为前 个字符(即 到 )的最大价值之和。
数组的状态转移方程
对于每个位置 (从 到 ),我们尝试从 (从 到 )往回看,看字串 到 是否满足每个字符只出现一次。那么 。
注意
如果 数组下标从 开始,所以长度为 的字串价值为 。
但是,直接这样做最坏情况下时间复杂度为 ,可能会超时。
优化思路
由于字符串只包含小写字母,最多 种字符,所以当我们从 往回遍历时,如果遇到重复字符就可以提前退出循环,我们用一个集合来记录当前字串的字符。
这样,我们最多检查 次,时间复杂度为 ,可以记为 。
代码实现步骤
-
读入 ,字符串 ,数组 ;
-
初始化 数组,大小为 ,;
-
对于 从 到 :初始化集合为 ,从 开始一直循环到 ,如果这个字符已经在集合里了,就退出循环,否则将 加入集合,继续更新 数组。
-
输出 。
代码
CPP#include<bits/stdc++.h>
using namespace std;
const int N=1e5+50;
int n;
string s;
long long a[N],dp[N];//防止溢出
int mp[120];
int main(){
ios::sync_with_stdio(0);//加速输入输出速度
cin.tie(0),cout.tie(0);
cin>>n;
cin>>s;
for(int i=0;i<n;i++){
cin>>a[i];
}
dp[0]=0;
for(int i=1;i<=n;i++){
unordered_set<char> st;
for(int j=i-1;j>=0;j--){
if(st.find(s[j])!=st.end())break;//如果该字串中存在该字符了,就退出循环
st.insert(s[j]);//否则就加入新的
dp[i]=max(dp[i],dp[j]+a[i-j-1]);//推导公式
}
}
cout<<dp[n];
return 0;//好习惯
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...