給出一個由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; } }