题意
给定2个长度为n的字符串s1,s2。给定操作:
- 选择整数k<=n
- 将字符串s1的前k个元素,和字符串s2的后k个元素,做交换。
比如n=5, k=2,则s1[1,2], s2[4,5] = s2[4,5], s1[1,2]
可以执行上述操作任意次,问最终,s1和s2能否相等。相等输出YES,否则输出NO
思路
我们观察发现,字符串s1的第i个元素和字符串s2的倒数第i个元素,1<=i<=n,我们发现,这2个元素的相对位置都保持不变。因为每次交换,s1的第i个元素(i<=k),就是交换到了s2的倒数第i个位置。
利用上述这一发现,我们来构建无序元素对(s1[i],s2[n+1-i])(1<=i<=n),如果这些无序元素对:
- 出现次数为奇数次的,满足该元素对两个的值相等,即s1[i]==s2[n+1-i];
- 且出现次数为奇数次的,数量不超过1
那么则可以最终使s1==s2
证明:
如果满足上述2个条件,说明s1+reverse(s2)可以构成回文字符串。此时s1==s2
其次,还有一个必要条件,s1上第i个元素的位置(或者s2上倒数第i个元素),可以放置到s1的[1,n]任意一个位置。
假设s1的大于i的位置已经放置好了。现在我们要将s1的第j个元素放置到第i个位置。
- 令k=j,此时我们则可以将s1的第j个位置,交换到s2的最后一个位置
- 如果我们需要交换元素对(因为我们上面提到的元素对,都是无序的),则可以令k=1,将该元素对交换。
- 令k=i,此时s2的最后一个位置的元素,就被交换到s1的第i个位置。
如下例子,原始j=2,目标i=4
贴一个官方样例
代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pcc pair<char, char>
#define inf 0x3f3f3f3f
const int maxn = 200010;
int n;
char s[maxn], s2[maxn];
map<pcc, int> mp;
void solve() {
scanf("%d", &n);
scanf("%s%s", s, s2);
mp.clear();
for (int i = 0; i < n; ++i) {
char a = s[i], b = s2[n-1-i];
if (a > b) {
swap(a, b);
}
++mp[{a, b}];
}
int tot = 0;
bool flag = true;
for (auto p: mp) {
if (p.second % 2 == 0) { // skip even number
continue;
}
pcc tmp = p.first;
// 1. if pair has odd number, with different elements
if (p.first.first != p.first.second) {
flag = false;
break;
}
++tot;
}
// 2. num of pair with odd number should not over 1.
flag = flag && (tot < 2);
printf("%s\n", flag ? "YES" : "NO");
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
solve();
}
}