ARC E - Don't Be a Subsequence DP

题目链接http://arc081.contest.atcoder.jp/tasks/arc081_c

题目大意:给你一个字符串,问不是这个字符串的最短字典序最小子序列是什么。如果一个字符串t是字符串s的子串,那么t可以由s通过删除0个或多个字符得到。

解题思路:我们先来确定字符串的长度,然后再通过长度的值递推出来子串。

如果t不是s的子序列,设字符c是t的第一个元素,那么

如果c在s中没有出现过,则t就是c

否则的话,设i是s中c第一次出现的位置,那么t.substr(2) 一定不是s.substr(i + 1)的子序列

因此我们设dp[i]为从第i(0 <= i <= s.length())个字符开始的不是s的子串的长度,那么有:

如果c('a' ~ 'z')在s中从第i + 1个位置开始未出现过,则dp[i] = 1

否则dp[i] = min(dp[nxt[i][j]] + 1)    0 <= j < 26,  nxt[i][j]指字符j在s中从第i+1个位置开始第一次出现的位置,初始值为-1

另一方面 nxt[i][j] = (str[i + 1] == 'a' + j)? i + 1: nxt[i + 1][j]

那么如果我们要找字典序最小的话:

如果dp[i] == 1, 则第一个满足nxt[i][c - 'a] == -1的字符c就是所求字符串末尾字符

否则的话当前字符应为满足dp[i] == dp[nxt[i][c - 'a']] + 1的第一个字符c, i = nxt[i][c - 'a']

代码:

 

 1 char str[maxn]; 
 2 int nxt[maxn][30], dp[maxn];
 3 
 4 void solve(){
 5     memset(nxt, -1, sizeof(nxt));
 6     int len = strlen(str + 1);
 7     for(int i = len - 1; i >= 0; i--){
 8         for(int j = 0; j < 26; j++){
 9             nxt[i][j] = (str[i + 1] == 'a' + j)? i + 1: nxt[i + 1][j];
10         }
11     }
12     memset(dp, 0x3f, sizeof(dp));
13     for(int i = len; i >= 0; i--){
14         bool flag = false;
15         for(int j = 0; j < 26; j++){
16             if(nxt[i][j] == -1){
17                 flag = true;
18                 dp[i] = 1;
19                 break;
20             }
21         }
22         if(flag) continue;
23         for(int j = 0; j < 26; j++){
24             if(nxt[i][j] != -1)
25                 dp[i] = min(dp[i], dp[nxt[i][j]] + 1);
26         }
27     }
28     for(int i = 0; i <= len; ){
29         if(dp[i] == 1){
30             for(int j = 0; j < 26; j++) {
31                 if(nxt[i][j] == -1){
32                     printf("%c", j + 'a');
33                     break;
34                 }
35             }
36             break;
37         }
38         for(int j = 0; j < 26; j++) {
39             if(nxt[i][j] != -1 && dp[i] == dp[nxt[i][j]] + 1){
40                 printf("%c", j + 'a');
41                 i = nxt[i][j];
42                 break;
43             }
44         }
45         
46     }
47     printf("\n");
48 }
49 int main(){
50     scanf("%s", str + 1);
51     solve();
52 }

 

题目:

E - Don't Be a Subsequence


Time limit : 2sec / Memory limit : 256MB

Score : 600 points

Problem Statement

A subsequence of a string S is a string that can be obtained by deleting zero or more characters from S without changing the order of the remaining characters. For example, arcartistic and (an empty string) are all subsequences of artisticabc and ci are not.

You are given a string A consisting of lowercase English letters. Find the shortest string among the strings consisting of lowercase English letters that are not subsequences of A. If there are more than one such string, find the lexicographically smallest one among them.

Constraints

  • 1≤|A|≤2×105
  • A consists of lowercase English letters.

Input

Input is given from Standard Input in the following format:

A

Output

Print the lexicographically smallest string among the shortest strings consisting of lowercase English letters that are not subsequences of A.


Sample Input 1

Copy
atcoderregularcontest

Sample Output 1

Copy
b

The string atcoderregularcontest contains a as a subsequence, but not b.


Sample Input 2

Copy
abcdefghijklmnopqrstuvwxyz

Sample Output 2

Copy
aa

Sample Input 3

Copy
frqnvhydscshfcgdemurlfrutcpzhopfotpifgepnqjxupnskapziurswqazdwnwbgdhyktfyhqqxpoidfhjdakoxraiedxskywuepzfniuyskxiyjpjlxuqnfgmnjcvtlpnclfkpervxmdbvrbrdn

Sample Output 3

Copy
aca

 

posted @ 2017-08-21 10:30  EricJeffrey  阅读(139)  评论(0编辑  收藏  举报