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