$\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. VS2010,VS2013 Datagridview控件的编辑列功能,弹窗界面被挤扁了

    搜了很久,没找到解决办法,在一个角落看到说要卸载Framework,实践后可以,发出来记一下. 解决办法: 发现自己电脑上多了Framework4.8,可能安装VS2013的时候自动安装的. 卸载了F ...

  2. arcgis python 获得表字段的唯一值

    #获得唯一值 by gisoracle def getuniqueValue(inTable,inField): rows = arcpy.da.SearchCursor(inTable,[inFie ...

  3. Async and Await (Stephen Cleary)

    https://blog.stephencleary.com/2012/02/async-and-await.html Most people have already heard about the ...

  4. bootstrap 上下页滚动

    <!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8" ...

  5. C#问答题与附解收集(三)

    post.get的区别 答: GET把参数包含在URL中,POST通过request body传递参数.GET请求在URL中传送的参数是有长度限制的,而POST没有.使用post提交的页面在点击[刷新 ...

  6. onNewIntent

    当Activity不是Standard模式,并且被复用的时候,会触发onNewIntent(Intent intent) 这个方法,一般用来获取新的Intent传递的数据 我们一般会把MainAcit ...

  7. flask_security学习笔记

    [Flask Security]当不能通过认证的时候制定跳转   Flask Security这个插件能对用户权限进行很好的控制.通过三个model实现:User,存放用户数据Role,存放角色数据U ...

  8. smarty获得当前url的方法分享

    http://{$smarty.server.SERVER_NAME}/{$smarty.server.REQUEST_URI} 注释: 复制代码代码如下: {$smarty.server.SERVE ...

  9. 工作流调度器之Azkaban

    Azkaban 1. 工作流调度器概述 1.1. 为什么需要工作流调度系统 一个完整的数据分析系统通常都是由大量任务单元组成:shell脚本程序,java程序,mapreduce程序.hive脚本等 ...

  10. JAVA 基础编程练习题40 【程序 40 字符串排序】

    40 [程序 40 字符串排序] 题目:字符串排序. package cskaoyan; public class cskaoyan40 { @org.junit.Test public void a ...