• Codeforces724D [字符串][乱搞][贪心]


    /*
    不要低头,不要放弃,不要气馁,不要慌张
    题意:给你一个区间长度n和一个字符串,要求在字符串中选择一些symbol使得字符串的任意长度为n的子区间都存在至少一个symbol。
    任意选取symbol,输出符合条件的symbol所有集合按照任意顺序排序的字典序最小的字符串。
    思路:
    1.明确 aaab 的字典序要小于aab。而aaab的字典序要小于aaabb。
    那么假如从a到x(x是某个字母)全部采用也无法符合题意,但是从a到x+1全部采用能符合题意。
    我们需要做的是,找最少需要多少个x+1使得在采用a到x所有字母的前提下,使用尽量少的x+1符合题意。
    2.以下思路可能过绕。(因为看别人AC代码很短)所以慎入。
    aft[i][j]代表在第i个位置以后距离第i个位置最近的j字母距离第i个位置的距离。
    然后每加入一个字母就用now[i]更新,代表距离第i个位置以后第i个位置最近的被选为symbol的字母距离第i个位置的距离。
    然后找到刚才提到的x+1以后就可以贪心得安排选取哪些使得采用的数目最小。
    坑:坑在最后的贪心啦。这题做完以后,我对自己的逻辑产生了很大的质疑...以后逻辑要多靠脑子想,不能一味依赖手动检测,否则效率太低了...嗷嗷
    
    */
    
    #include<bits/stdc++.h>
    using namespace std;
    char jilu[100050];
    int shu[100050];
    int bbf[100050][28],aft[100050][28],me[100050][28],now[100050],bf[100050];
    int gg[30];
    int rel[100050];
    int main()
    {
        int n;
        scanf("%d",&n);
        scanf("%s",jilu);
        int len=strlen(jilu);
        for(int i=0;i<len;i++){
            shu[i]=jilu[i]-'a';
        }
        for(int i=0;i<len;i++){
            gg[shu[i]]++;
        }
        for(int i=0;i<26;i++){
            int st=-1e9;
            for(int j=0;j<len;j++){
                if(shu[j]==i)st=j;
                bbf[j][i]=st;
            }
            st=1e9;
            for(int j=len-1;j>=0;j--){
                if(shu[j]==i)st=j;
                aft[j][i]=st;
            }
            for(int j=0;j<len;j++){
                me[j][i]=aft[j][i]-j+1;
            }
        }
        for(int i=0;i<26;i++){
            bool ok=1;
            for(int j=0;j<=len-n;j++){
                bf[j]=now[j];
                if(i==0)now[j]=me[j][i];
                else now[j]=min(now[j],me[j][i]);
                if(now[j]>n)ok=0;
            }
            if(ok){
                int num=0;
                if(i==0){
                    for(int j=0;j<=len-n;j++){
                        rel[j]=j;
                    }
                    num=len-n+1;
                }
                else{
                    for(int j=0;j<=len-n;j++){
                        if(bf[j]>n)rel[num++]=j;
                    }
                }
                for(int j=0;j<i;j++){
                    for(int k=0;k<gg[j];k++)printf("%c",'a'+j);
                }
                int aaa=0,bbb=0,bf=-1;
                bool ook=0;
                while(bbb<len){
                    if(shu[bbb]==i){
                        if(bbb-rel[aaa]+1>n){
                            ook=1;
                            printf("%c",'a'+i);
                            while(aaa<num&&rel[aaa]<=bf){
                                aaa++;
                            }
                        }
                        if(aaa==num)break;
                        bf=bbb;
                    }
                    bbb++;
                }
                if(!ook||aaa!=num)printf("%c",'a'+i);
                break;
            }
        }
        return 0;
    }
  • 相关阅读:
    __module__ 和 __class__
    __str__ 和 __repr
    __getitem__ __setitem__ __delitem__ 使用
    授权
    __getattr__ __delattr__ __setattr__ __getattribute__使用(重写python提供的错误信息)
    __import__
    hasattr getattr setattr delattr --> (反射)
    类三大特性(继承 多态 封装)
    静态方法@staticmethod
    类方法@classmethod
  • 原文地址:https://www.cnblogs.com/tun117/p/5943900.html
Copyright © 2020-2023  润新知