Atcoder-ABC-454-D (xx)

题目描述

给你一个字符串 A,它由 (x) 组成。
你可以对 A* 任意次数、任意顺序地执行以下两种操作:

  • 选中 A* 中的一个 (xx) 子串,将它替换成 xx
  • 选中 A* 中的一个 xx 子串,将它替换成 (xx)

给你另一个字符串 B,它也由 (x) 组成。请判断是否可以通过上述操作把 A 变成 B*。

你需要处理 T 组测试数据,每组独立求解。

什么是子串字符串 S  子串 是通过删掉开头和结尾任意数量的字符得到的字符串。
比如,ab  abc 的子串,但 ac 不是。

约束条件

  • 1≤T≤3×10^5
  • AB 的长度都在 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
image

比如第一组测试,你可以这样把 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;
}
posted @ 2026-04-24 20:44  xmgene  阅读(3)  评论(0)    收藏  举报