题目翻译,给定t组数据,每组数据包含一个字符串s,两个长度为m的字符串l和r,要求判断是否存在一个长度为m的字符串res,满足l[i]<=res[i]<=r[i](i->0~m)且不是s的子序列
贪心
首先对于所有满足l<res<r的字符串,我们只需判断是否存在一个字符串不是子序列即可,那么我们让res成为子序列的可能性最小
如何得到最优的字符串呢,我们发现对于res[i]来说可以从l[i]到r[i]中任意选择,对于第i个字符,我们求得在经过i-1次选择后,res[i]的选项中在s中首次出现的位置,然后在所有首次出现的位置中选那个首次位置最靠后的字符串,这样可以保证选择完第i个字符后,s中可以选择的字符数量最少,因此成为子序列的可能性最小,因为每次都是选中首次出现的所以不用担心前面会有重复的
判断条件,当q[j]的长度为0时,说明不存在该子序列
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <set>
#include <utility>
#include <vector>
#include <queue>
#include <map>
using namespace std;
string s,l,r;
int t,m;
queue<int> q[10];
void solve(){
for(int i=0;i<10;i++)
while(q[i].size()) q[i].pop();
cin>>s;
cin>>m;
cin>>l>>r;
for(int i=0;i<s.length();i++){
q[s[i]-'0'].push(i);
}
int last=-1;//记录上次选中的字符位置
for(int i=0;i<m;i++){
for(int j=l[i]-'0';j<=r[i]-'0';j++){
if(q[j].size()==0){//说明该可选方案不为子序列
cout<<"YES"<<endl;
return;
}
int u=q[j].front();
if(u>last){
last=u;
}
}
for(int j=0;j<10;j++){//更新首次出现的位置,当last越大时每个q减少的越多,只要有一个q[j]减少为0,就不能为子序列
while(q[j].size()&&q[j].front()<=last) q[j].pop();
}
}
cout<<"NO"<<endl;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>t;
while(t--){
solve();
}
}
- Educational Codeforces Password Strong Roundeducational codeforces password strong educational password strong div2 codeforces password strong 1845c educational codeforces round rated educational codeforces round 151 construction educational codeforces round educational codeforces round 147 cf-educational educational codeforces round educational codeforces round 158 educational codeforces contest round