zoukankan      html  css  js  c++  java
  • 2019 Multi-University Training Contest 1 String(序列自动机+贪心)

    题意:给你一个字符串 现在要你找出一个长度为k的字典序最小的子序列 且要求每个字母出现的个数要满足要求

    思路:我们可以贪心构造每一位字符 优先放置字典序更小的字符 判断是否合法即可

    #include <bits/stdc++.h>
    using namespace std;
    const double pi = acos(-1.0);
    const int N = 1e5+7;
    const int inf = 0x3f3f3f3f;
    const double eps = 1e-6;
    typedef long long ll;
    const ll mod = 1e7+9;
    string s;
    int l[N],r[N],suf[N][26],nex[N][26],use[26],k;
    void work(string s){
        int len=s.length();
        for(int i=0;i<26;i++){
            suf[len+1][i]=0;
            nex[len+1][i]=-1;
            use[i]=0;
        }
        
        for(int i=len;i>=1;i--){
            for(int j=0;j<26;j++){
                suf[i][j]+=suf[i+1][j];
                nex[i][j]=nex[i+1][j];
            }
            suf[i][s[i-1]-'a']++;
            nex[i][s[i-1]-'a']=i;
        }
    }
    vector<char> ans;
    bool check(int po,int sz){
        int len=0; int num=0;
        for(int i=0;i<26;i++){
            if(use[i]+suf[po][i]<l[i]) return false;
            len+=use[i]+min(suf[po][i],r[i]-use[i]);
            num+=max(0,l[i]-use[i]);
        }
        if(len<k) return false;
        if(num+sz>k) return false;
        return true;
    }
    int main(){
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        while(cin>>s>>k){
            memset(suf,0,sizeof(suf));
            memset(nex,0,sizeof(nex));
            ans.clear();
            for(int i=0;i<26;i++){
                cin>>l[i]>>r[i];
            }
            work(s);
            int now=0; int sz=0;
            bool f=1;
            int len=s.length();
            while(now+1<=len&&sz+1<=k){
                bool ff=0;
                for(int i=0;i<26;i++){
                    if(nex[now+1][i]!=-1&&use[i]<r[i]){
                        use[i]++;
                        if(check(nex[now+1][i],sz+1)){
                            ans.push_back(i+'a');
                            sz++;
                            now=nex[now+1][i];
                            ff=1;
                            break;
                        }
                        use[i]--;
                    }
                }
                if(!ff){
                    f=0;
                    break;
                }
            }
            if(f){
                for(int i=0;i<sz;i++)
                    cout<<ans[i];
                cout<<endl;
            }else{
                cout<<"-1"<<endl;
            }
        }
        return 0;
    }
  • 相关阅读:
    7、JavaScript总结——实现选项卡切换的效果
    6、JavaScript进阶篇③——浏览器对象、Dom对象
    5、JavaScript进阶篇②——函数、事件、内置对象
    4、JavaScript进阶篇①——基础语法
    3、DOM操作
    2、JavaScript常用互动方法
    1、JavaScript入门篇
    HTML5与CSS3网页设计
    JAVA程序设计
    Elasticsearch搭建问题汇总
  • 原文地址:https://www.cnblogs.com/wmj6/p/11363630.html
Copyright © 2011-2022 走看看