Atcoder-ABC-454-D (xx)
题目描述
给你一个字符串 A,它由 (、x、) 组成。
你可以对 A* 任意次数、任意顺序地执行以下两种操作:
- 选中 A* 中的一个
(xx)子串,将它替换成xx。 - 选中 A* 中的一个
xx子串,将它替换成(xx)。
给你另一个字符串 B,它也由 (、x、) 组成。请判断是否可以通过上述操作把 A 变成 B*。
你需要处理 T 组测试数据,每组独立求解。
什么是子串
字符串 的 子串 是通过删掉开头和结尾任意数量的字符得到的字符串。比如,
ab 是 abc 的子串,但 ac 不是。约束条件
- 1≤T≤3×10^5
- A 和 B 的长度都在 1 到 2*10^6 之间,且仅由
(、x、)组成。 - 所有测试数据中,所有 ∣A∣+∣B∣ 的长度总和不超过 2×10^6(其中 ∣A∣ 表示字符串 A 的长度)。
输入格式
输入从标准输入读取,格式如下:
T
case1
case2
⋮
caseT
每组测试数据格式:
A
B
输出格式
输出 T 行,第 i 行是第 i 组测试的答案。
如果能把 A 变成 B*,输出 Yes,否则输出 No。

比如第一组测试,你可以这样把 A 变成 B:
- 把 A 中第 1 到 4 个字符里的
(xx)替换成xx,操作后 A 变成xxx。 - 再把 A 中第 2 到 3 个字符里的
xx替换成(xx),操作后 A 变成x(xx)。
算法分析
目标:要把A变成B。
实现:如果用BFS搜索A串的每一个状态判断等不等于B,肯定会超时。想一想,稍加思考可以发现,正确解法是把A串和B串都变成最简形式,即把两串能去掉的括号都去掉,判断两串相不相等即可,用字符‘0‘表示删除的字符。
AC代码
#include<bits/stdc++.h>
using namespace std;
int T;
string a,b;
void shch(string &s,int len){//删除函数
for(int i = 1; i<=len; i++){
int l = i-1;
int r = i+2;
if(l>=1 && r<=len && s[i]=='x' && s[i+1]=='x'){
int j = l;
int k = r;
while(s[j]=='(' && s[k]==')'){
s[j--] = '0';
s[k++] = '0';
}
}
}
}
void check(int lena,int lenb){
string ta,tb;//化简后的字符串
for(int i = 1; i<=lena; i++){
if(a[i]!='0'){
ta.push_back(a[i]);//未删除就入串
}
}
for(int i = 1; i<=lenb; i++){
if(b[i]!='0'){
tb.push_back(b[i]);//未删除就入串
}
}
if(ta==tb){//判断相不相等
cout<<"Yes\n";
}else{
cout<<"No\n";
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);//输入、输出加速
cin>>T;
while(T--){
cin>>a>>b;
if(a==b){
cout<<"Yes\n";//输入时相等就直接输出
continue;
}
int lena = a.size();
int lenb = b.size();
a = ' '+a;
b = ' '+b;
shch(a,lena);//删除
shch(b,lenb);//删除
check(lena,lenb);//判等
}
return 0;
}

浙公网安备 33010602011771号