CF1256F Equalizing Two Strings(冒泡排序、思维)

题意:

给出两个长度相同的字符串,询问能否通过每次翻转两个串相同长度的区间使得两个串一样。

题解:

/*
 *CF1256F
 *题意:
 *给定两个长度一样的仅有小写字母的字符串
 *每次可以从两个串中分别选一个长度相等的子串进行翻转
 *询问是否存在使两个串相等的操作方案
 *题解:
 *首先每种字母的个数不同,直接NO
 *如果有某种字母出现次数超过2次,直接YES,可以将两个字母移动到一起后
 *通过冒泡排序的方法无限次操作 
 *接下来只考虑每种字母只出现一次的情况
 *冒泡排序每次能消除一次逆序对
 *如果两者逆序奇偶性相同,只要小的那个在冒泡排序完成后不断浪费次数即可
 *所以奇偶性相同YES
 *不相同NO
 */
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+100;
int t;
int n;
string s1,s2;
int cnt[2][30];
int main () {
    cin>>t;
    while (t--) {
        int f=1;
        memset(cnt,0,sizeof(cnt));
        cin>>n;
        cin>>s1;
        cin>>s2;
        for (int i=0;i<s1.size();i++) cnt[0][s1[i]-'a']++;
        for (int i=0;i<s2.size();i++) cnt[1][s2[i]-'a']++;
        for (int i=0;i<26;i++) if (cnt[0][i]!=cnt[1][i]) f=0;
        int f1=0;
        for (int i=0;i<26;i++) if (cnt[0][i]>1) {
            f1=1;
        } 
        if (f==1&&f1==1) {
            printf("YES\n");
            continue;
        }
        memset(cnt,0,sizeof(cnt));
        int sum1=0,sum2=0;
        for (int i=0;i<n;i++) {
            int p=s1[i]-'a';
            for (int j=p+1;j<26;j++) sum1+=cnt[0][j];
            int p1=s2[i]-'a';
            for (int j=p1+1;j<26;j++) sum2+=cnt[1][j];
            cnt[0][p]++;
            cnt[1][p1]++;
        }
        if (sum1%2!=sum2%2) f=0;
        if (f)
            printf("YES\n");
        else
            printf("NO\n");
    }
} 

 

posted @ 2020-09-08 19:40  zlc0405  阅读(188)  评论(0编辑  收藏  举报