输入1行字符串S,所有字符均为小写,字符串的长度为L。(1 <= L <= 100000)。
输出包含S中所有出现过的字符,每个字符各1个,并且字典序最小的S的子序列。
babbdcc
abdc
利用栈来解决问题。
例babbdcc
我们栈为空, 放入b
之后对于a,a<b(栈顶),我们贪心想要想输出a,但是前面已经b了,我们看看字符串后面适合还有b,如果有的话,就把这个栈顶的b去掉,在考虑新的栈顶,最后把a加进去。
现在栈只有a
下一个b,b>a(栈顶),放入。
就是这样来,对于新的和栈元素比较,如果大于,直接放进入,等于不做处理,小于看看后面是否还有相同的,有的话去掉栈顶把当前放入。没有的话直接把当前放入即可。不过需要注意每个元素只能有一个。需要一个vis来判断一下。
另外,统计后面是否还有相同的字符需要进行预处理,提前统计每个字符出现的次数。用掉一个就减一
#include<bits/stdc++.h>
using namespace std;
int num[26];
int vis[26];
char str[100005];
int main()
{
cin>>str;
int len = strlen(str);
memset(num, 0, sizeof(num));
memset(vis, 0, sizeof(vis));
for(int i = 0; i < len; i++)
num[str[i]-'a']++; //统计每一个字符出现的次数
stack<char> st;
for(int i = 0; i < len; i++)
{
while(!st.empty() && st.top() > str[i] && !vis[str[i] - 'a'] && num[st.top() - 'a'] > 0)
{
vis[st.top() - 'a']--;
st.pop();
}
if(vis[str[i] - 'a'] == 0)
{
st.push(str[i]);
vis[str[i] - 'a'] = 1;
}
num[str[i] - 'a']--;
}
char res[100];
int tot = 0;
while(!st.empty()){
res[tot++] = st.top();
st.pop();
}
for(int i = tot - 1; i >= 0; i--)
printf("%c", res[i]);
printf("\n");
return 0;
}