D、CSL 的字符串 【栈+贪心】 (“新智认知”杯上海高校程序设计竞赛暨第十七届上海大学程序设计春季联赛)

题目传送门:https://ac.nowcoder.com/acm/contest/551#question

题目描述 

CSL 以前不会字符串算法,经过一年的训练,他还是不会……于是他打算向你求助。

给定一个字符串,只含有可打印字符,通过删除若干字符得到新字符串,新字符串必须满足两个条件:
  • 原字符串中出现的字符,新字符串也必须包含。
  • 新字符串中所有的字符均不相同。
  • 新字符串的字典序是满足上面两个条件的最小的字符串。
 

输入描述:

仅一行,有一个只含有可打印字符的字符串 s。
 
|s|105|s|≤105

输出描述:

在一行输出字典序最小的新字符串。
示例1

输入

复制
bab

输出

复制
ab
示例2

输入

复制
baca

输出

复制
bac

备注:

ASCII字符集包含 94 个可打印字符(0x21 - 0x7E),不包含空格。

解题思路:

贪心,用一个栈逆序保存答案,第一次扫一遍字符串,记录每一个字符最后出现的位置(用于判断栈内元素是否为该类字符的最后那个字符)。

第二次扫一遍字符串,如果比栈顶元素大或者当前空栈,压栈。否则,如果栈顶的元素比当前元素大并且不是该元素最后的元素,即后面还有栈顶这种元素,那么栈顶元素出栈。

最后逆序输出栈内元素。

AC code:

 1 #include <bits/stdc++.h>
 2 #define INF 0x3f3f3f3f
 3 #define LL long long
 4 #define inc(i, j, k) for(int i = j; i <= k; i++)
 5 #define rep(i, j, k) for(int i = j; i < k; i++)
 6 #define mem(i, j) memset(i, j, sizeof(i))
 7 #define gcd(i, j) __gcd(i, j)
 8 using namespace std;
 9 
10 const int MAXN = 2e5+10;
11 string str;
12 stack<char>ss;
13 map<char, int>mmp;
14 string ans;
15 map<char, bool>vis;
16 int main()
17 {
18     cin >> str;
19     int len = str.size();
20     rep(i, 0, len){
21         mmp[str[i]]=i;
22     }
23 
24 
25     rep(i, 0, len){
26         if(!vis[str[i]]){
27             if(ss.empty() || str[i] > ss.top()){
28                 vis[str[i]] = true;
29                 ss.push(str[i]);
30                 continue;
31             }
32             while(!ss.empty() && ss.top() > str[i] && mmp[ss.top()] > i){
33                 vis[ss.top()] = false;
34                 ss.pop();
35             }
36             //puts("zjj");
37             ss.push(str[i]);
38             vis[str[i]] = true;
39         }
40     }
41     while(!ss.empty()){
42 //        printf("%c", ss.top());
43         ans+=ss.top();
44         ss.pop();
45     }
46     for(int i = ans.size()-1; i >= 0; i--)
47         printf("%c", ans[i]);
48     puts("");
49     return 0;
50 }
View Code

猜你喜欢

转载自www.cnblogs.com/ymzjj/p/10665114.html