首页 > 代码库 > C - 字典序最小的子序列 51nod1255
C - 字典序最小的子序列 51nod1255
C - 字典序最小的子序列
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 1280000/640000 KB (Java/Others)
Submit Status
Problem Description
给出一个由a-z组成的字符串S,求他的一个子序列,满足如下条件:
1、包含字符串中所有出现过的字符各1个。
2、是所有满足条件1的串中,字典序最小的。
例如:babbdcc,出现过的字符为:abcd,而包含abcd的所有子序列中,字典序最小的为abdc。
1、包含字符串中所有出现过的字符各1个。
2、是所有满足条件1的串中,字典序最小的。
例如:babbdcc,出现过的字符为:abcd,而包含abcd的所有子序列中,字典序最小的为abdc。
Input
单样例输入。
每个输入1行字符串S,所有字符均为小写,字符串的长度为L。(1 ≤ L ≤ 107)。
所有样例中只有一个样例 L > 105
Output
输出包含S中所有出现过的字符,每个字符各1个,并且字典序最小的S的子序列。
Sample Input
babbdcc
Sample Output
abdc
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const int N=1e7+10; 5 const int INF=0x3f3f3f3f; 6 int cas=1,T; 7 char s[N],ans[N]; 8 int a[N],n; 9 vector<int>q[26];10 int main()11 {12 // freopen("1.in","w",stdout);13 // freopen("21.in","r",stdin);14 // freopen("21.out","w",stdout);15 // scanf("%d",&T);16 while(scanf("%s",s)==1)17 {18 int n=0;19 for(;s[n];n++) q[s[n]-‘a‘].push_back(n);20 a[n]=0;21 for(int i=n-1;i>=0;i--)22 {23 int id=s[i]-‘a‘;24 a[i]=a[i+1]|(1<<id);25 }26 int d=0,an=0,id=0;27 while(d!=a[0])28 {29 for(int i=0;i<26;i++) if((d&(1<<i))==0 && q[i].size())30 {31 auto it=lower_bound(q[i].begin(),q[i].end(),id);32 if(it!=q[i].end())33 {34 if((d|a[*it])==a[0])35 {36 ans[an++]=i+‘a‘;37 d|=1<<i;38 id=*it;39 break;40 }41 }42 }43 }44 ans[an]=0;45 puts(ans);46 }47 // printf("time=%.3lf\n",(double)clock()/CLOCKS_PER_SEC);48 return 0;49 }
题解:
用一个int的bit表示每个字母是否存在,设字母集合为U,从后往前扫一遍算出存在后缀和,即a[i]表示这个数后面有哪些字母
再从前往后扫一遍,记录已有字母的集合U1,对于位置i,每次取能与U1,a[i]并起来能得到全集U 的最小的字母,最后字母集合U1为所求结果
C - 字典序最小的子序列 51nod1255
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。