CSL 的字符串

链接:https://ac.nowcoder.com/acm/contest/551/D
来源:牛客网
 

题目描述

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

给定一个字符串,只含有可打印字符,通过删除若干字符得到新字符串,新字符串必须满足两个条件:

  • 原字符串中出现的字符,新字符串也必须包含。
  • 新字符串中所有的字符均不相同。
  • 新字符串的字典序是满足上面两个条件的最小的字符串。

输入描述:

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

|s|≤10^5

输出描述:

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

示例1

输入

bab

输出

ab

示例2

输入

baca

输出

bac

备注:

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

题解

先预处理一下字符串,计算出每个字符出现的次数。

用数组ans模拟栈来存储选择的字符,cnt记录栈内字符个数,ans[cnt]是栈顶元素。

用cnt数组flag标记字符是不是在栈内

然后从左到右扫一遍,对于每个位置会出现两种情况。

1.这个字符已经在栈内,那么跳过,不用处理。

2.这个字符不在栈内,那么比较这个字符与栈顶元素的大小  ,如果栈顶字符大于当前字符,并且栈顶字符在之后的位置还会出现,那么出栈,然后继续比较。知道不满足上述情况,当前位置的元素进栈。

对于每个位置的字符,最多入栈一次,出栈一次,所以时间复杂度是O(n)

代码

#include<algorithm>
#include <iostream>
#include<cstring>
#include <cstdio>
#include<stack>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int num[200];
char c[maxn];
char ans[maxn];
int cnt=0;
bool flag[200];
int main(){
    scanf("%s",c);
    int len=strlen(c);
    for(int i=0;i<len;i++) num[c[i]]++;
    for(int i=0;i<len;i++){
        num[c[i]]--;
        if(flag[c[i]]) continue;
        else{
            while(cnt>0&&c[i]<ans[cnt]&&num[ans[cnt]]){
                flag[ans[cnt]]=false;
                cnt--;
            }
            cnt++;
            ans[cnt]=c[i];
            flag[c[i]]=true;
        }
    }
    for(int i=1;i<=cnt;i++) printf("%c",ans[i]);
    cout<<endl;
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值