田径场上的字符串(双端队列解法)

Description

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

Input

多组输入:

仅一行,有一个只含有可打印字符的字符串 s。长度小于等于1e5

Output

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

Sample Input Copy

4444555666

Sample Output Copy

456

HINT

字符串中包含空格

错误写法:
我一开始的思路即是将字符串排序后,用unique去重。显然是错误的。下面为一开始的错误代码。

#include<bits/stdc++.h>
#include <iostream>
using namespace std;
#define ios ios::sync_with_stdio(false);
int main()
{
    char a[100020];
    while(gets(a))
    {
        vector<char> s(a,a+strlen(a));
        vector<char>::iterator new_end;
        sort(s.begin(),s.end(),greater<char>());
        new_end = unique(s.begin(),s.end());
        s.erase(new_end,s.end());
        while(!s.empty())
        {
            cout<<s.back();
            s.pop_back();
        }
        cout<<'\n';
    }
    return 0;
}

解题思路: 题意为在字符串的基础上保留一个每种出现的字符,并使保留下的字符串最小。(不能将字符串进行排序)
样例分析:

  • 输入aaabbbb输出ab
  • 输入bbbbaaa输出ab
  • 输入aaabbaa输出ab
  • 输入bbaabbb输出ab
#include<bits/stdc++.h>
#include<algorithm>
using namespace std;
#define ios ios::sync_with_stdio(false);
int vis[100020];//标记这个字符是否找过
int cnt[100020];//寻找最后一个字符
char s[100020];
int main()
{
    deque <char> str;
    while(gets(s))
    {
        memset(vis,0,sizeof(vis));
        memset(cnt,0,sizeof(cnt));
        for(int i=0; i<strlen(s); i++)
        {
            vis[s[i]] = 1;
            cnt[s[i]]++;
        }
        for(int i=0; i<strlen(s); i++)
        {
            cnt[s[i]]--;
            if(vis[s[i]]==1)
            {
                vis[s[i]] = 0;
                while(!str.empty() && cnt[str.back()] > 0 && str.back() > s[i])
                {
                    vis[str.back()] = 1;
                    str.pop_back();
                }
                str.push_back(s[i]);
            }
        }
        while(!str.empty())
        {
            cout<<str.front();
            str.pop_front();
        }

        cout<<'\n';
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值