题面

思路

进行长度为 2 的操作相当于交换相邻两个字符

首先,如果一个字符串有两个字符相同,先用两两交换使之相邻

那么这一字符串一直交换这两个相同的字符,就相当于不变

另一个字符串进行两两交换,则能变成任意排列,所以有限次操作总能相同

排除以上特殊情况后,剩下的最长长度为 26 (暴力???)

引理1:假设存在方法使两个字符串相同了,再进行无限次操作,只要两者选的区间相同,都相同

引理2:假设字符串 S1 能通过 n 次两两交换变成 字符串 S2,若 n 是 2 的倍数, 则满足题目要求

证明:对 S2 同一区间进行 2 的倍数次操作,不会改变

所以

那么我们不妨将两个都操作成升序序列,通过两两交换的方式,次数就是逆序对

如果两个字符串的次数差是 2 的倍数,就满足条件

代码

#include <bits/stdc++.h>

using namespace std;

const int N = 2e5+7;

int q, n;
int cnt[2][26], tot[2];
string s[2];

int main()
{
    cin >> q;
    while (q--) {
        cin >> n;
        int flag = 0;
        memset(cnt, 0, sizeof cnt);
        for (int i = 0; i < 2; ++i) {
            cin >> s[i];
            for (int j = 0; j < n; ++j)
                ++cnt[i][s[i][j]-'a'];
        }
        flag = 1;
        for (int i = 0; i < 26; ++i) {
            if (cnt[0][i] != cnt[1][i]) {
                flag = 0;
                break;
            }
        }
        if (!flag) {
            cout << "NO" << endl;
            continue;
        }
        flag = 0;
        for (int i = 0; i < 26; ++i) {
            if (cnt[0][i] > 1 || cnt[1][i] > 1) {
                flag = 1;
                break;
            }
        }
        if (flag) {
            cout << "YES" << endl;
            continue;
        }

        memset(cnt, 0, sizeof cnt);
        tot[0] = tot[1] = 0;
        for (int i = 0; i < 2; ++i) {
            for (int j = 0; j < n; ++j) {
                for (int k = s[i][j]-'a'+1; k < 26; ++k)
                    tot[i] += cnt[i][k];
                ++cnt[i][s[i][j]-'a'];
            }
        }
        cout << (tot[0]%2 == tot[1]%2 ? "YES" : "NO") << endl;
    }
    return 0;
}