Codeforces Round #124 (Div. 2) / C. Lexicographically Maximum Subsequence

C. Lexicographically Maximum Subsequence
time limit per test
 2 seconds
memory limit per test
 256 megabytes
input
 standard input
output
 standard output

You've got string s, consisting of only lowercase English letters. Find its lexicographically maximum subsequence.

We'll call a non-empty string s[p1p2... pk] = sp1sp2... spk(1 ≤ p1 < p2 < ... < pk ≤ |s|) a subsequence of string s = s1s2... s|s|.

String x = x1x2... x|x| is lexicographically larger than string y = y1y2... y|y|, if either |x| > |y| and x1 = y1, x2 = y2, ... , x|y| = y|y|, or exists such number r (r < |x|, r < |y|), that x1 = y1, x2 = y2, ... , xr = yr and xr + 1 > yr + 1. Characters in lines are compared like their ASCII codes.

Input

The single line contains a non-empty string s, consisting only of lowercase English letters. The string's length doesn't exceed 105.

Output

Print the lexicographically maximum subsequence of string s.

Sample test(s)
input
ababba
output
bbba
input
abbcbccacbbcbaaba
output
cccccbba
Note

Let's look at samples and see what the sought subsequences look like (they are marked with uppercase bold letters).

The first sample: aBaBBA

The second sample: abbCbCCaCbbCBaaBA

分析:

题目大意就是找一个字典序最大的子序列(和序列的其他子序列相比)。

一开始的想法是先对序列从大到小稳定排序(用的stable_sort)并记录位置,然后从大的开始输出,要求是后面的字符的原来的位置要大于前面取出的字符最后的位置(也就是说这个字符要比比它大的字符在原来序列中的后面出现,所以需要稳定排序,不然相等的字符再处理时会漏掉)。思路没有什么问题,可没想到提交后超时了。。。看来stable_sort很慢呐。。。

我的超时代码:

 1 #include <iostream>
 2 #include <cmath>
 3 #include <cstring>
 4 #include <algorithm>
 5 
 6 using namespace std;
 7 
 8 struct F
 9 {
10     char s;
11     int id;
12 }f[10001];
13 
14 bool cmp(const F &a,const F &b)
15 {
16     return a.s>b.s;
17 }
18 
19 int main()
20 {
21     char s[10001];
22 
23     cin>>s;
24 
25     int strl=strlen(s);
26 
27     for (int i=0;i<strl;i++)
28     {
29         f[i].s=s[i];
30         f[i].id=i;
31     }
32     stable_sort(f,f+strl,cmp);
33 
34     int max=-1;
35     for (int i=0;i<strl;i++)
36             if (f[i].id>max)
37             {
38                 max=f[i].id;
39                 cout<<f[i].s;
40             }
41     cout<<endl;
42     return 0;
43 }

到最后也没想到什么办法~哎。。。

思路:

比赛后看了Div.2的rank1的代码,发现原来这么简单。。。

其实这道题朴素的想法就是每次找一个串中最大的字符取出,这些串就是每次取完的最大字符后面的串。比如abbcbccacbbcbaaba刚开始的串就是本身,然后顺序找到最大的是第四个位置上的c,则取出来,然后串变为bcacbbcbaaba;然后又找到最大的是第二个位置上的c,然后串变成acbbcbaaba;然后又取出第二个位置上的c,串变成bbcbaaba,直到串长度为零。

但这个想法显然会超时,比我上面的想法更超时,因为每次搜串的最大字符时都要把整个字符全扫一遍。重复工作太多,很浪费时间。

那么换个思路,从前往后不行,就从后往前嘛。最后一个字符肯定要取,然后只要前面判断的字符大于等于已经取出过的字符就拿出来就行。顺序一遍扫完。K.O.

 1 #include<cstdio>
 2 #include<cstring>
 3 char s[111111],t[111111];
 4 int main(){
 5     scanf("%s",s);
 6     int tot,i;
 7     char lst;
 8     lst=0;
 9     tot=-1;
10     for (i=strlen(s)-1;i>=0;i--){
11         if (s[i]>=lst){
12             t[++tot]=s[i];
13             lst=s[i];
14         }
15     }
16     for (;tot>=0;tot--) putchar(t[tot]);
17     puts("");
18     return 0;
19 }

哎。。。好简单呐~~~自己还是太弱了。。。

举杯独醉,饮罢飞雪,茫然又一年岁。 ------AbandonZHANG
原文地址:https://www.cnblogs.com/AbandonZHANG/p/2598361.html