CSL 的字符串(“新智認知”杯上海高校程序設計競賽暨第十七屆上海大學程序設計春季聯賽)

鏈接:https://ac.nowcoder.com/acm/contest/551/D
來源:牛客網

題目描述

CSL 以前不會字符串算法,經過一年的訓練,他還是不會……於是他打算向你求助。

給定一個字符串,只含有可打印字符,通過刪除若干字符得到新字符串,新字符串必須滿足兩個條件:

  • 原字符串中出現的字符,新字符串也必須包含。
  • 新字符串中所有的字符均不相同。
  • 新字符串的字典序是滿足上面兩個條件的最小的字符串。

輸入描述:

僅一行,有一個只含有可打印字符的字符串 s。

|s|≤105|s|≤105

輸出描述:

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

示例1

輸入

bab

輸出

ab

示例2

輸入

baca

輸出

bac

備註:

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

思路:使用棧進行模擬,如果當前字符已經在棧中,則跳過(保證了每個字符只存一次),否則進行如下操作:如果當前字符比棧頂元素小並且棧頂元素在之後的序列中仍有剩餘,就彈出棧頂元素,持續這個過程直到棧頂元素比當前元素小或者棧頂元素沒有剩餘,然後把當前字符放入棧中(保證了所有字符都會存入棧中)

以上思路來源於https://blog.csdn.net/Septembre_/article/details/88942986

舉個例子:字符串dbdcebhgdac!ad    模擬一下過程:

1. 開始棧爲空,放入d.此時棧裏(下面也都是從棧底到棧頂來說的)有d

2. b比棧頂小,而且d在後面出現,所以刪掉d,把b放入,此時棧裏有b

3.d比棧頂大,直接放入,此時棧裏有bd

4.c比棧頂小,而且d在後面出現,所以刪掉d,把c放入,此時棧裏有bc

5.e比棧頂大,直接放入,此時棧裏有bce

6.b棧裏面有,直接跳過不用管,此時棧裏有bce

7.h比棧頂大,直接放入,此時棧裏有bceh

8.g比棧頂大,直接放入,此時棧裏有bcehg

9.d比棧頂小,但是棧頂元素在接下來的字符串中沒有出現過,所以直接放入d,此時棧裏有bcehgd

10.a比棧頂小,而且d在後面出現,所以刪掉d,把a放入,此時棧裏有bcehga

11.c棧裏面有,直接跳過不用管,此時棧裏有bcehga

12.!比棧頂小,而且a在後面出現.所以刪掉a,把!放入,此時棧裏有bcehg!

13.a比棧頂大,直接放入,此時棧裏有bcehg!a

14.d比棧頂大,直接放入,此時棧裏有bcehg!ad

所以最後應該輸出bcehg!ad(注意從棧底往棧頂輸出,可用遞歸)

#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <deque>
#include <queue>
#include <stack>
#include <set>
using namespace std;
typedef long long ll;
const int MAX=998244353;
const int M=1e5+7;
stack <char> st;
void f()
{
    if(st.empty())
    {
        return ;
    }
    char c=st.top();
    st.pop();
    f();
    cout<<c;
}
int main()
{
    string s;
    ll i,j,flag[200]={0},len;
    cin>>s;
    len=s.size();
    for(i=0;i<len;i++)
    {
        flag[s[i]]++;//標記接下來的字符出現的個數
    }
    char vis[200]={0};//標記字符是否在棧中
    for(i=0;i<len;i++)
    {
        flag[s[i]]--;
        if(vis[s[i]]==0)
        {
            vis[s[i]]=1;
            while(!st.empty()&&s[i]<st.top()&&flag[st.top()]!=0)
            {
                vis[st.top()]=0;
                st.pop();
            }
            st.push(s[i]);
        }
    }
    //從下往上輸出
    f();
    cout<<endl;
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章