当前位置: 首页 > news >正文

【CF】Day47——Educational Codeforces Round 178 (Rated for Div. 2) E

这场A-E真的简单,E题稍微卡了一会,还需要dp优化

E. Unpleasant Strings

题目:

思路:

很有学习价值的一题

这题有两个难点,第一是如何快速判断一个 t 是不是 s 的子序列,第二个是如何快速多次查找最小添加数量 

我们先来解决第一个,由于要是 s 的子序列,那我们肯定要找到 t 的第一个字符在 s 中最前的位置,然后第二个字符在 s 中最前的位置(且要在第一个字符的位置之后),那么这样的查找我们怎么优化呢?如果每次循环一遍字符串肯定是不行的,所以我们要想一个快速的查找位置的方法,我们观察到每次查找都是比上一个位置大,即具有单调性,那么对于这种问题我们显然可以使用二分查找来写,因此我们记录一个数组 f[i],其代表 i 字符的位置有哪些,那么查找过程就很明显可以写出来了,我们枚举每个位置,并且选择第一个比之前位置大的合法位置,如果找不到,说明这个字符串不是子序列,否则必定是

那么找子串结束了,接下来如何快速知道要几个字符呢?

这里我直接给出我最后的优化方法,我们在判断是否合法时我们能知道子串最后一个字符对应的哪里,我们希望越快得出结果最好,那么我们可以考虑如果我们能在 O(1) 的复杂度里得出来不就很完美吗,我们观察一下,对于同一个位置我们最好的添加方式其实可以从后面的状态转移过来,比如对于 bcb,我们之后添加的方式可能是 bcba bcbb bcbc ,那我们只需要选择里面需要添加次数最少的可能即可,那么对于 bcb 的答案就是 min(bcba bcbb bcbc) + 1

那么其实答案就出来了,我们可以定义 dp[i] 为当前字符串结尾在 i 处时所需要的最小花费,那么显然转移就是 dp[i] = min(dp[j] + 1) 其中 j 就是后续添加 26 种字符之后的位置的可能,特别注意可能为 0,所以记得判断一下

具体实现看代码

代码:

#include <iostream>
#include <algorithm>
#include<cstring>
#include<cctype>
#include<string>
#include <set>
#include <vector>
#include <cmath>
#include <queue>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <stack>
#include <memory>
using namespace std;
#define int long long
#define yes cout << "Yes\n"
#define no cout << "No\n"
int n, k;
string s;
vector<vector<int>> f(30);
vector<int> dp(1000006,(int)1e9);
void Init()
{for (int i = 0; i < n; i++){f[s[i] - 'a'].push_back(i);}for (int i = n - 1; i >= 0; i--){for (int j = 0; j < k; j++){auto it = upper_bound(f[j].begin(), f[j].end(), i);if (it == f[j].end()){dp[i] = 1;break;}dp[i] = min(dp[i], dp[*it] + 1);}}
}int getPos(const string& t)
{int temppos = -1;for (auto c : t){auto it = upper_bound(f[c - 'a'].begin(), f[c - 'a'].end(), temppos);if (it == f[c - 'a'].end()){return -1;}temppos = *it;}return temppos;
}
void solve()
{int q;cin >> q;for (int i = 0; i < q; i++){string t; cin >> t;if (getPos(t) == -1){cout << 0 << endl;continue;}cout << dp[getPos(t)] << endl;}
}signed main()
{cin.tie(0)->sync_with_stdio(false);int t = 1;//cin >> t;while (t--){cin >> n >> k;cin >> s;Init(); solve();}return 0;
}

相关文章:

  • C++ Lambda表达式中 与 =的作用
  • DeepSeek驱动的金市情绪量化:NLP解析贸易政策文本的情绪传导路径
  • 第十节:文本编辑
  • ES搜索知识
  • Qt窗口关闭特效:自底而上逐渐消失
  • 【补题】Codeforces Round 664 (Div. 1) A. Boboniu Chats with Du
  • 蓝桥杯赛后总结
  • AI时代生产工厂制造业数字化转型培训师培训讲师唐兴通教授专家顾问清华大学讲授AI库存降本增效智能制造供应链生产调度智能管理设备健康
  • 微波功率器件的发展
  • 部署若依项目到服务器遇到的问题
  • 要搞一个PHP的工程,顺到手科普下VS Code
  • openGauss新特性 | HTAP新特性介绍
  • 西门子PLC S7-1200 电动机的软启动控制
  • DeepSeek-V3 解读,第一部分:理解 Multi-Head Latent Attention
  • RHCSA Linux 系统 文件系统权限
  • 关于我的算法文章学习路线
  • Go与Cpp的本质区别
  • 量子机器学习中的GPU加速实践:基于CUDA Quantum的混合编程模型探索
  • Java对集合进行操作,赋值新字段
  • k8s术语之Replication Controller
  • 马上评|启动最高层级医政调查,维护医学一方净土
  • 武汉楼市新政:二孩、三孩家庭购买新房可分别享受6万元、12万元购房补贴
  • 广东省副省长刘红兵任湖南省委常委、宣传部部长
  • 体坛联播|欧冠半决赛阿森纳主场不敌巴黎,北京男篮险胜山西
  • 交通运输部:预计今年五一假期全社会跨区域人员流动量将再创新高
  • 央行召开落实金融“五篇大文章”总体统计制度动员部署会议