51nod1255 字典序最小的子序列


給出一個由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
 
 
題目思路:用一個棧來儲存答案,從左到右遍歷一遍字符串,如果在棧中(有標記)直接continue。如果串中字符小於棧頂且字符串中還有棧頂元素則出棧,且取消標記。(這里應該用while循環,有可能棧中多個元素都要出棧),沒有標記的直接進棧,標記。最后倒序輸出就是了。
代碼:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<stack>
using namespace std;
char s[100050];
int flag[30];
stack<char>st;
int vis[30];
char ans[30];
int main()
{
    while(cin>>s)
    {
        memset(flag,0,sizeof(flag));
        memset(vis,0,sizeof(vis));//標記是否在棧內 
        int len=strlen(s);
        for(int i=0;i<len;i++)
        {
            flag[s[i]-'a']++;//計算數量 
        }
        st.push(s[0]);
        vis[s[0]-'a']=1;//標記 
        flag[s[0]-'a']--;
        for(int i=1;i<len;i++)
        {
            flag[s[i]-'a']--;
            if(vis[s[i]-'a'])//在棧內,就不用操作,直接下一個元素 
                continue;
            while(!st.empty()&&st.top()>s[i]&&flag[st.top()-'a']>0)//s[i]比棧頂元素小且后面還有棧頂元素,則出棧 
            {
                vis[st.top()-'a']=0;
                st.pop();
            }
            st.push(s[i]);//沒有標記的進棧 
            vis[s[i]-'a']=1;    
        }    
        int sum=0;
        while(!st.empty())
        {
            ans[sum++]=st.top();
            st.pop();
        }
        for(int i=sum-1;i>=0;i--)//倒序輸出 
            cout<<ans[i];
        cout<<endl;
    }
} 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM