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

[ARC081E] Dont Be a Subsequence 题目分析

题目概述

求所有不是 A 的子序列的最短小写英文字母字符串中字典序最小的一个。

分析

一个类似于 CSP2025-S 中第三题的动态规划。

倒着做。

\(f_i\) 表示以 \(A_i\) 为开头的子序列不在 \(A_{i\dots |A|}\) 出现的最短长度。

然后从后面挑一个转移即可。

但是我们发现这样子是 \(\mathcal{O}(n^2)\) 的。

但是我们可供转移的字符集最多只有 \(26\) 个。

于是优化状态:设 \(f_i\) 表示以字符 \(i\) 为开头的子序列不在当前 \(A\) 的后缀当中的最短长度。

\[f_i=1+\min_x f_{p_x} \]

然后就做完了。

代码

时间复杂度 \(\mathcal{O}(n)\)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <stdlib.h>
#include <algorithm>
#include <vector>
#define int long long
#define N 200005
#define M 30
using namespace std;
char s[N + M];
int n;
int p[M],f[M],g[N + M];
signed main(){scanf("%s",s + 1);n = strlen(s + 1);for (int i = 0;i < 26;i ++) s[++n] = i + 'a',p[i] = n;for (int i = n - 26;i >= 0;i --) {g[i] = p[0];for (int j = 1;j < 26;j ++)if (f[j] < f[s[g[i]] - 'a']) g[i] = p[j];if (i) f[s[i] - 'a'] = f[s[g[i]] - 'a'] + 1,p[s[i] - 'a'] = i;}for (int x = g[0];x;x = g[x]) putchar(s[x]);return 0;
}

入门黑科技:子序列自动机

利用空间换时间的做法。

推荐阅读:https://www.cnblogs.com/zhln/p/18432582

\(nxt_{i,j}\) 表示从 \(i\) 开始字符 \(j\) 最开始的位置。

然后按照序列的顺序跑bfs就可以了。

代码

时间复杂度 \(\mathcal{O}(n)\)

以下代码来自zjc5:

#include <bits/stdc++.h>
using namespace std;
const int N = 200010;
char ch[N], ans[N];
int n, nxt[N][26], pre[N], cnt;
bool vs[N];
int main() {cin >> (ch + 1);n = strlen(ch + 1);for (int i = n; i; i--) {for (int j = 0; j < 26; j++)nxt[i][j] = nxt[i + 1][j];nxt[i][ch[i] - 'a'] = i;}//预处理queue<int>q;vs[0] = 1;q.push(0);while (!q.empty()) {int x = q.front();q.pop();for (int i = 0; i < 26; i++) {int t = nxt[x + 1][i];if (!t) {//第一个未被找到的字符串ans[++cnt] = 'a' + i;while (x) {ans[++cnt] = ch[x];x = pre[x];}for (int i = cnt; i; i--)cout << ans[i];return 0;} else if (vs[t])continue;pre[t] = x, vs[t] = 1;q.push(t);}}return 0;
}
http://www.hskmm.com/?act=detail&tid=29172

相关文章:

  • AI代理从概念验证到生产部署全流程
  • Azure Arc C2即服务:攻击与防御实战指南
  • CPU中的加法运算与减法运算
  • macos单独打开模拟器simulator
  • 子序列自动机学习笔记
  • 2018牛客网暑期ACM多校训练营(第一场)
  • 20232311 2025-2026-1 《网络与系统攻防技术》实验一实验报告
  • 你的认知模式,决定了你的人生高度
  • 在Typora中数学公式无法显示问题
  • 洛谷个人主页
  • 原码、反码、补码
  • C++ - 从字符串中提取一个数的若干种写法
  • ABC 日志
  • 251012
  • 如何在UE中创建动态枚举
  • 能连上 GitHub(SSH 验证成功),却 push 失败?常见原因与逐步解决方案 - 详解
  • 换根dp的一个trick
  • 搭建SSH服务于RK3399平台上的Ubuntu 18.04,实现远程连接
  • 深入探讨MySQL的二进制日志(binlog)选项
  • sparkml 多列共享labelEncoder - 详解
  • 一键解决MetaHuman播放动画时头部穿模问题
  • 忽然很好奇为什么素未谋面的大家都知道我是学姐?
  • UE网络编程完全指南:UDP TCP WebSocket实现详解
  • 配置Nginx服务器在Ubuntu平台上
  • 缓存一致性验证秘笈
  • 从十五岁的今天写给十六岁的明天
  • kali U盘启动持久化
  • 深入解析:Telerik UI for ASP.NET MVC 2025 Q3
  • Java依记 DAY02 - I
  • 元推理:汉字的发音,同音也是某种同构?