题目
https://codeforces.com/contest/1662/problem/D
大意:字典为 {A,B,C},给两个字符串u, v,问能不能通过增减{AA, BB, CC, ABAB, BCBC}的操作,将 u 变成 v。
思路
- 一开始,我们发现了 ABA, CBC 可以和 B 互相变;BAB 可以和 A 互相变;BCB 可以和 C 互相变。于是写了个不断删 AA, BB, CC, 替换 ABA, CBC, BAB, BCB 的代码,结果假了。
- 然后就想,好像 A 和 C 看起来很对称,B看起来相对特殊一点。B在中间,两边可以随便加东西。然后就想到,B左侧的一个 A/C 可以移到 B 右侧去,也就是说,B在串中的位置是可以随意改变的(不改变其他字母的相对顺序)。而 A/C 的相对顺序则没法改变。
- 这样一来,就可以将所有单词构建成几个等价类,全都归化到最简形式:将所有B移到最左边,再删掉所有可删的 AA, BB, CC。
代码
#include <bits/stdc++.h>
using namespace std;
char a[300], b[300];
const char *solve()
{
string A, B;
scanf("%s%s", a, b);
int cnt1=0;
int cnt2=0;
for (char *p=a; *p; p++) {
if (*p == 'B') cnt1^=1;
else A+=*p;
}
for (char *p=b; *p; p++) {
if (*p == 'B') cnt2^=1;
else B+=*p;
}
if (cnt1^cnt2) return "NO";
//printf("# %s %s\n", A.c_str(), B.c_str());
for (int done=0; !done && (done=1); ) {
if (~A.find("AA")) {
done=0;
A.erase(A.find("AA"), 2);
}
else if (~A.find("CC")) {
done=0;
A.erase(A.find("CC"), 2);
}
if (~B.find("AA")) {
done=0;
B.erase(B.find("AA"), 2);
}
else if (~B.find("CC")) {
done=0;
B.erase(B.find("CC"), 2);
}
}
//printf("# %s %s\n", A.c_str(), B.c_str());
if (A!=B) return "NO";
return "YES";
}
int main()
{
int ttt;
scanf("%d", &ttt);
while (ttt--) {
puts(solve());
}
return 0;
}
/*
8
A
B
B
C
C
A
AA
BB
BB
CC
CC
AA
ABAB
BCBC
ABC
CBA
*/