【Codeforces 1256F】Equalizing Two Strings

分类讨论

题目大意:

给定两个字符串,每次可以任选一个长度 $L$,并翻转两个字符串中一个长度为 $L$ 的子串。问是否能通过有限次操作,使得两个字符串相等。

题解:

首先先判断每个字符的出现次数相等,不相等显然不可能。

然后,翻转长度为 $L$ 的串,可以通过有限次交换相邻两个字符来做到相同的效果。

于是就相当于每次交换相邻两个字符。

我们可以考虑对字符串进行排序。

如果一个字符串中有两个字符相等,那么两个字符串中,一个已经排好序,可以通过不断交换两个相同的字符来“浪费”步数,同时把另外一个排好序即可。这样一定可以使两个串相等。

否则,交换相邻两个字符,必然使得逆序对个数的奇偶性发生改变。那么判一下两个字符串的逆序对奇偶性是否相等即可。

Code:

#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
using namespace std;
const int N=2e5+6;
char s[N],t[N];
int buc1[128],buc2[128];
int T;
int chk(){
    string a(s),b(t);
    sort(a.begin(),a.end());
    sort(b.begin(),b.end());
    if(a!=b)return 0;
    for(int i=0;i+1<a.length();++i)
        if(a[i]==a[i+1])return 2;
    return 1;
}
int main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>T;
    while(T--){
        int n;
        cin>>n>>s>>t;
        int x=chk();
        if(x==0){
            cout<<"NO\n";
            continue;
        }
        memset(buc1,0,sizeof buc1);
        memset(buc2,0,sizeof buc2);
        int f1=0,f2=0;
        for(int i=0;i<n;++i){
            for(int j=s[i]+1;j<='z';++j)f1+=buc1[j];
            for(int j=t[i]+1;j<='z';++j)f2+=buc2[j];
            ++buc1[s[i]],++buc2[t[i]];
        }
        x+=(f1&1)==(f2&1);
        if(x>1)
            cout<<"YES\n";
        else
            cout<<"NO\n";
    }
    return 0;
}