码迷,mamicode.com
首页 > 其他好文 > 详细

2019 Multi-University Training Contest 1 String(序列自动机+贪心)

时间:2019-08-16 14:31:01      阅读:85      评论:0      收藏:0      [点我收藏+]

标签:ems   cin   out   tor   mes   mem   ring   最小   void   

题意:给你一个字符串 现在要你找出一个长度为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;
}

 

2019 Multi-University Training Contest 1 String(序列自动机+贪心)

标签:ems   cin   out   tor   mes   mem   ring   最小   void   

原文地址:https://www.cnblogs.com/wmj6/p/11363630.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!