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

Posted wmj6

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;

 

以上是关于2019 Multi-University Training Contest 1 String(序列自动机+贪心)的主要内容,如果未能解决你的问题,请参考以下文章

2019 Multi-University Training Contest 6

2019 Multi-University Training Contest 6

2019 Multi-University Training Contest 6

2019 Multi-University Training Contest 3

2019 Multi-University Training Contest 2

2019 Multi-University Training Contest 2