CF1907B YetnotherrokenKeoard 题解
FlyPancake · · 题解
CF1907B YetnotherrokenKeoard 题解
My Blog!
模拟题,题面还是挺清晰的。
Ideas
暴力:依次输入字符,遇到 b 或 B 就向前遍历是否有对应的小写字母或大写字母,有则删去。时间复杂度应该为
正解:用两个栈分别存储小写字母和大写字母(这里我个人认为存其对应在字符串中的序号比较方便一些,因为接下来有关栈的操作并不用涉及到入栈的字符),若遇到字符 b 或 B 则将栈顶元素出栈,并将 b 或 B 标记为已删去,出栈元素标记为已删去(这时存序号的优势就体现出来了)。最后遍历一遍字符串,未标记为删除的输出即可。时间复杂度应该为
Code
#include <bits/stdc++.h>
using namespace std;
bool is_pop[1000005];
int main(){
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int T; cin>>T;
while(T--){
string str; cin>>str;
for(int i=0; i<str.length(); i++) is_pop[i] = false; // 多测清空
stack<int> S1, S2;
for(int i=0; i<str.length(); i++){
if(str[i]=='b'){
if(!S1.empty()) is_pop[S1.top()] = true, S1.pop(); // 栈不为空则弹出栈顶,并标记为已删除
is_pop[i] = true; // 标记字符 b 为已删除
}
else if(str[i]=='B'){
if(!S2.empty()) is_pop[S2.top()] = true, S2.pop(); // 同理
is_pop[i] = true;
}
else if(str[i]>='a' && str[i]<='z')
S1.push(i); // 直接存其对应在字符串中的序号
else if(str[i]>='A' && str[i]<='Z')
S2.push(i);
}
for(int i=0; i<str.length(); i++)
if(!is_pop[i]) cout<<str[i]; // 未被删除则输出
cout<<"\n";
}
return 0;
}
Continue
你以为这就完了?
其实,这道题还有一种更短的做法:反序遍历输入的字符串,若遇到 b 或 B ,将其出现次数加 1。再在前面遇到可删去的对应字母就就将其出现次数减 1。如果无出现次数就将当前字符存入答案字符串中,最后将答案字符串反序并输出即可(目前最优解)。
#include <bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int T; cin>>T;
while(T--){
string str, ans; cin>>str;
int b = 0, B = 0;
for(int i=str.length()-1; i>=0; i--){
if(str[i]=='b') b++;
else if(str[i]=='B') B++;
else if(str[i]>='a' && str[i]<='z' && b) b--;
else if(str[i]>='A' && str[i]<='Z' && B) B--;
else ans += str[i];
}
reverse(ans.begin(), ans.end());
cout<<ans<<"\n";
}
return 0;
}