题目链接
大意:给你一个字符串,让你找出长度为k的子序列满足每个字符出现次数的区间满足所有限制。
思路:先倒着处理一遍字符串,然后贪心选k次,每次从 a−z判断是否能选即可。
细节处理一下即可:
#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mp make_pair
#define pb push_back
using namespace std;
LL gcd(LL a,LL b){return b?gcd(b,a%b):a;}
LL lcm(LL a,LL b){return a/gcd(a,b)*b;}
LL powmod(LL a,LL b,LL MOD){LL ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
const int N = 2e5 +11;
char a[N];
int K;
int l[33],r[33],cnt[N][33],res[33];
int n,nx[N][33];
int main(){
ios::sync_with_stdio(false);
while(cin>>a+1){
cin>>K;
n=strlen(a+1);
for(int i=0;i<26;i++)cin>>l[i]>>r[i];
for(int i=0;i<26;i++)nx[n+1][i]=cnt[n+1][i]=0;
for(int i=n;i>=1;i--){
for(int j=0;j<26;j++)nx[i][j]=nx[i+1][j],cnt[i][j]=cnt[i+1][j];
nx[i][a[i]-'a']=i;
cnt[i][a[i]-'a']++;
}
int L=0;
for(int i=0;i<26;++i)res[i]=0;
int dad=1;
queue<char>ans;
for(int i=1;i<=K;i++){
char sta='a';
int can=0;
for(int j=0;j<26;j++){
if(!cnt[L+1][j])continue;
if(res[j]>=r[j])continue;
res[j]++;
int need=0;
int nxt;
nxt=nx[L+1][j];
for(int k=0;k<26;k++){
if(l[k]>res[k])need+=l[k]-res[k];
}
if(K-i<need||K-i>n-nxt){res[j]--;continue;}
int ok=0;
for(int k=0;k<26;k++){
if(cnt[nxt][k]+res[k]<l[k]){
ok=1;
break;
}
}
if(!ok){sta+=j;can=1;break;}
res[j]--;
}
if(!can){
dad=0;
break;
}
L=nx[L+1][sta-'a'];
ans.push(sta);
}
if(ans.size()<K)cout<<"-1\n";
else {
while(!ans.empty()){
cout<<ans.front();
ans.pop();
}
cout<<endl;
}
}
return 0;
}