题目描述
CSL 以前不会字符串算法,经过一年的训练,他还是不会……于是他打算向你求助。
给定一个字符串,只含有可打印字符,通过删除若干字符得到新字符串,新字符串必须满足两个条件:
原字符串中出现的字符,新字符串也必须包含。
新字符串中所有的字符均不相同。
新字符串的字典序是满足上面两个条件的最小的字符串。
输入描述:
仅一行,有一个只含有可打印字符的字符串 s。
|
s
|
≤
10
5
|s|≤105
输出描述:
在一行输出字典序最小的新字符串。
示例1
输入
复制
bab
输出
复制
ab
示例2
输入
复制
baca
输出
复制
bac
备注:
ASCII字符集包含 94 个可打印字符(0x21 - 0x7E),不包含空格。
利用单调队列的性质,尽量维护队列前面的字符比当前的字符小,如果队列尾部的字符,在余下的字符里没有了,则不能出队;否则,如果当前字符小于队列尾部的字符,那么队尾字符出队。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
#define mp make_pair
#define pb push_back
#define fi first
#define se second
int cnt[505];
int vis[505];
int main()
{
string s;
cin >> s;
int len = s.size();
string ans;
memset(vis,0,sizeof(vis));
for(int i = 0;i < len;++i){
cnt[s[i]]++;
}
for(int i = 0;i < len;++i){
cnt[s[i]]--;
if(!vis[s[i]]){
while(ans.size() && s[i] < ans.back() && cnt[ans.back()]){
vis[ans.back()] = 0;
ans.pop_back();
}
vis[s[i]] = 1;
ans += s[i];
}
}
cout << ans << endl;
return 0;
}