目录
题目:
题目描述:
给你长度为 n 的两个只包含 ' a ' , ' b ' , ' c ' 的字符串 s 和 t
你能进行的操作:对串中相邻的两个字符,你可以将 ' ab ' 转化为 ' ba ' , 或者将 ' bc ' 转化为 ' cb '
问:能不能经过任意次操作,将 s 字符串 转换为 t 字符串
思路:
如果我们对 s 串从前往后与t串进行比对,我们会发现,只有碰到不一样的才需要从后面找,但我们会发现,根据题目对操作的要求,后面的 ' a ' 不能跨越前面的 ' b ' 或 ' c ' ,后面的 ' b ' 不能跨越前面的 ' c ' ,后面的 ' c ' 不能跨越前面的 ' a '
具体关系如下图所示:
(解释: a → b 表示 a 可以从右边向左跨越 b ,红色箭头表示不能从右往左跨越。)
所以我们可以分类讨论,在遍历的过程中,如果一样就继续,如果不一样:
①如果 t 串在这个位置需要的是 ' a ' :
那就别想了,后面的 a 无论如何也往前挪不动,因为 ' a ' 无法跨越 ' b ' 或者 ' c '
②如果 t 串在这个位置需要的是 ' b ' :
那么我们肯定是找 s 串这个位置后边出现的第一个 ' b ' 来挪到这个位置。但是如果后面没有 ' b ' 了,或者中间隔了 ' c ' 那就一定错误,因为 ' b ' 不可能从右往左跨越 ' c ' 。但如果找到了就进行交换
③如果 t 串在这个位置需要的是 ' c ' :
那么我们肯定是找 s 串这个位置后边出现的第一个 ' c ' 来挪到这个位置。但是如果后面没有 ' c ' 了,或者中间隔了 ' a ' 那就一定错误,因为 ' c ' 不可能从右往左跨越 ' a ' 。但如果找到了就进行交换
所以我们现在需要的是什么?一种能快速找到后面第一次出现的字符的位置的数据结构,所以我想到了 set 容器( 对放入的元素自动排列 )
我们可以开三个set分别来存放 ' a ' , ' b ' , ' c ' 的出现位置,这样用 set 中的 begin 位置存放的数据就是这个字符在后面第一次出现的位置。
思路有了,具体操作请看AC代码:
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
char s[N];
char t[N];
int main()
{
std::ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int q; cin >> q;
while (q--)
{
int n;
cin >> n;
set<int>a;
set<int>b;
set<int>c;
cin >> s + 1;
cin >> t + 1;
int flag = 1;//代表是否能成功,1成功,0失败
for (int i = 1; i <= n; i++)
{
if (s[i] == 'a')a.insert(i);
else if (s[i] == 'b')b.insert(i);
else c.insert(i);
}
for (int i = 1; i <= n; i++)
{
//遍历到每一位,先删除对应set中的第一位
if (s[i] == 'a')a.erase(i);
else if (s[i] == 'b')b.erase(i);
else c.erase(i);
//如果一样就下一位
if (s[i] == t[i])continue;
//如果不一样就分类讨论
if (t[i] == 'a')
{
flag = 0;
break;
}
else if (t[i] == 'b')
{
if (s[i] == 'c' || b.size() == 0 ||
(c.size() != 0 && *c.begin() < *b.begin()))
{
flag = 0;
break;
}
//如果找到了符合要求的字符,进行交换
swap(s[i], s[*b.begin()]);
//set中也要更新
a.insert(*b.begin());
b.erase(b.begin());
}
else if (t[i] == 'c')
{
if (s[i] == 'a' || c.size() == 0 ||
(a.size() != 0 && *a.begin() < *c.begin()))
{
flag = 0;
break;
}
swap(s[i], s[*c.begin()]);
b.insert(*c.begin());
c.erase(c.begin());
}
}
if (flag)
cout << "YES" << '\n';
else
cout << "NO" << '\n';
}
return 0;
}