51nod 1255 字典序最小的子序列 贪心

给出一个由a-z组成的字符串S,求他的一个子序列,满足如下条件:

1、包含字符串中所有出现过的字符各1个。
2、是所有满足条件1的串中,字典序最小的。

例如:babbdcc,出现过的字符为:abcd,而包含abcd的所有子序列中,字典序最小的为abdc。
Input
输入1行字符串S,所有字符均为小写,字符串的长度为L。(1 <= L <= 100000)。
Output
输出包含S中所有出现过的字符,每个字符各1个,并且字典序最小的S的子序列。
Input示例
babbdcc
Output示例

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;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值