• C


     
    
    

    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。

    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
    ",(double)clock()/CLOCKS_PER_SEC);
    48     return 0;
    49 }
    solve.cpp

    题解:

    用一个int的bit表示每个字母是否存在,设字母集合为U,从后往前扫一遍算出存在后缀和,即a[i]表示这个数后面有哪些字母
    再从前往后扫一遍,记录已有字母的集合U1,对于位置i,每次取能与U1,a[i]并起来能得到全集U 的最小的字母,最后字母集合U1为所求结果

  • 相关阅读:
    oc对象的内存管理
    OC类的本质,深入探讨,load方法和initialize方法
    OC特有语法:分类category,给NSString增加方法计算字符串中数字的个数
    OC的类的构造方法
    OC的@property 和 @synthesize id
    HTML5 Canvas时间效果
    各浏览器的Hack写法【转】
    你自认为理解了JavaScript?【转】
    八大疯狂的HTML5 Canvas及WebGL动画效果——8 CRAZY ANIMATIONS WITH WEBGL AND HTML5 CANVAS【收藏】
    一些达成共识的JavaScript编码风格约定【转】
  • 原文地址:https://www.cnblogs.com/cdyboke/p/7010503.html
Copyright © 2020-2023  润新知