$\newcommand{\dp}{\mathsf{dp}}$
$\newcommand{\next}{\mathsf{next}}$

Let $S$ be a string of lower case English letters. If there can be found all subsequences of length $L$ in $S$, then $S$ can be divided into $L$ segments, each contains all the 26 letters, which implies length of $S$ is at least $26L$.

This observation leads us to a solution. Let $\dp[i]$ be the maximum number of the aforementioned segments that the suffix of $S$ that starts at index $i$ can be divided into. The DP can be done in $O(|S|)$ time. The shortest string that is not a subsequence of $S$ has a length of $M = \dp[0] + 1$ ($S$ is 0-indexed).

Let $\next[i][j]$ be the position of the first occurrence of letter $j$ to the right of position $i$ (including position $i$). We can compute the $\next$ array in $O(26|S|)$ time.

Using the $\next$ and $\dp$ arrays, we can construct the answer as follows:

Start with an empty string $T$. Iterate the $\dp[0] + 1$ positions of the answer string from left to right. For each position $i$, iterate over the letters from 'a' to 'z'. For each letter $j$, check whether it is possible to get an answer if we append $j$ to $T$. Let $k$ be position of the last letter of the first occurrence of $Tj$ in $S$ as a subsequence, it is ok to append letter $j$ to $T$ if the suffix $S[k + 1, |S|)$ does not contain all subsequences of length $M - |T| - 1$ i.e. $\dp[k + 1] < M - |T| - 1$. This check can be done efficiently, see the following code for detail.

code
 
int main() {
string s;
scan(s);
int n = SZ(s);
vb vis(26);
int cnt = 0;
vi dp(n + 1);
int length = 0;
down (i, n - 1, 0) {
if (!vis[s[i] - 'a']) {
vis[s[i] - 'a'] = true;
++cnt;
if (cnt == 26) {
++length;
fill(all(vis), false);
cnt = 0;
}
}
dp[i] = length;
} vv next(n, vi(26));

fill(all(next.back()), n);

next.back()[s.back() - 'a'] = n - 1;

down (i, n - 2, 0) {

rng(j, 0, 26) {

next[i][j] = s[i] - 'a' == j ? i : next[i + 1][j];

}

} ++length; int pos = 0;

while (length > 0) {

rng (j, 0, 26) {

int t = next[pos][j];

if (t < n && dp[t + 1] == length - 1) continue;

if (t < n) {

pos = t + 1;

}

cout << char('a' + j);

break;

}

--length;

}

cout << '\n';

return 0;

}

ARC081E. Don't Be a Subsequence的更多相关文章

  1. [LeetCode] Arithmetic Slices II - Subsequence 算数切片之二 - 子序列

    A sequence of numbers is called arithmetic if it consists of at least three elements and if the diff ...

  2. [LeetCode] Is Subsequence 是子序列

    Given a string s and a string t, check if s is subsequence of t. You may assume that there is only l ...

  3. [LeetCode] Wiggle Subsequence 摆动子序列

    A sequence of numbers is called a wiggle sequence if the differences between successive numbers stri ...

  4. [LeetCode] Increasing Triplet Subsequence 递增的三元子序列

    Given an unsorted array return whether an increasing subsequence of length 3 exists or not in the ar ...

  5. [LeetCode] Longest Increasing Subsequence 最长递增子序列

    Given an unsorted array of integers, find the length of longest increasing subsequence. For example, ...

  6. 动态规划求最长公共子序列(Longest Common Subsequence, LCS)

    1. 问题描述 子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串 cnblogs belong 比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与 ...

  7. 【LeetCode】Increasing Triplet Subsequence(334)

    1. Description Given an unsorted array return whether an increasing subsequence of length 3 exists o ...

  8. CF724D. Dense Subsequence[贪心 字典序!]

    D. Dense Subsequence time limit per test 2 seconds memory limit per test 256 megabytes input standar ...

  9. UVA 11404 Palindromic Subsequence[DP LCS 打印]

    UVA - 11404 Palindromic Subsequence 题意:一个字符串,删去0个或多个字符,输出字典序最小且最长的回文字符串 不要求路径区间DP都可以做 然而要字典序最小 倒过来求L ...

随机推荐

  1. Qt ASSERT:"QMetaObjectPrivate::get(smeta)->revision>= 7"in file kernel\qobject.cpp,line 2646

    qt5.6.1所做的工程在运行时出现该问题:该问题说的是信号槽中 函数的参数不匹配. 在qt4.8.4 中QThread 中查到assitant中定义void QThread::finished () ...

  2. 关于VGA显示实验的问题

    今天做了一个关于VGA的显示实验,但是由于产生的25M时钟不正确所以一直没有图像产生.刚开始的程序如下 虽然仿真的时候出现了时序,但是在下载到硬件的时候不正确. 后来改成 结果就正确了. 另外之前关于 ...

  3. wqy的B题

    wqy的B题 题意: 和一道叫机器翻译的题差不多,不过这道题要难一些,没有规定必须删除最早入队的. 解法: 解法和[POI2005]SAM-Toy Cars这道题差不多,考虑贪心. 每次选取下一次使用 ...

  4. GA算法及参数对结果的影响

    1.遗传算法简介 遗传算法是一种基于自然选择和群体遗传机理的搜索算法,它模拟了自然选择和自然遗传过程中的繁殖.杂交和突变现象.再利用遗传算法求解问题时,问题的每一个可能解都被编码成一个“染色体”,即个 ...

  5. Installing the Solidity Compiler¶

    Versioning¶ Solidity versions follow semantic versioning and in addition to releases, nightly develo ...

  6. kvm安装及简单使用

    1 cat /etc/redhat-release      CentOS release 6.4 (Final)2 egrep ‘vmx|svm’ /proc/cpuinfo3 yum -y ins ...

  7. JVM的线程

    我们使用java命令来运行一个程序,那么就需要启动JVM , 而jvm的启动就相当于启动了一个进程 , 而这个进程在启动的时候会自动启动一个线程,由这个线程去调用main方法,而这个线程就是主线程 ; ...

  8. 从零搭建配置Cuckoo Sandbox

    1.安装依赖 $ sudo apt-get install git mongodb libffi-dev build-essential python-django python python-dev ...

  9. Qt开发经验小技巧合集

    一.开发经验总结 当编译发现大量错误的时候,从第一个看起,一个一个的解决,不要急着去看下一个错误,往往后面的错误都是由于前面的错误引起的,第一个解决后很可能都解决了. 定时器是个好东西,学会好使用它, ...

  10. unity 读取灰度图生成按高程分层设色地形模型

    准备灰度图 1.高程按比例对应hue色相(hsv)生成mesh效果 o.color = float4(hsv2rgb(float3(v.vertex.y/100.0, 0.5, 0.75)), 1.0 ...