F. Equalizing Two Strings(Codeforces Round #598 (Div. 3))(思維-模擬)

F. Equalizing Two Strings(Codeforces Round #598 (Div. 3))(思維-模擬)

time limit per test:1 second
memory limit per test:256 megabytes
input:standard input
outputs:tandard output

Description

You are given two strings ss and tt both of length nn and both consisting of lowercase Latin letters.

In one move, you can choose any length len from 1 to n and perform the following operation:

  • Choose any contiguous substring of the string ss of length len and reverse it;
  • at the same time choose any contiguous substring of the string tt of length len and reverse it as well.

Note that during one move you reverse exactly one substring of the string s and exactly one substring of the string tt.

Also note that borders of substrings you reverse in ss and in tt can be different, the only restriction is that you reverse the substrings of equal length. For example, if len=3len=3 and n=5n=5, you can reverse s[13]s[1…3] and t[35],s[24]t[3…5], s[2…4] and t[24]t[2…4], but not s[13]s[1…3] and t[12]t[1…2].

Your task is to say if it is possible to make strings ss and tt equal after some (possibly, empty) sequence of moves.

You have to answer qq independent test cases.

Input

The first line of the input contains one integer q(1q104)q (1≤q≤10^4) — the number of test cases. Then qq test cases follow.

The first line of the test case contains one integer n(1n2105)n (1≤n≤2⋅10^5) — the length of ss and tt.

The second line of the test case contains one string ss consisting of nn lowercase Latin letters.

The third line of the test case contains one string tt consisting of nn lowercase Latin letters.

It is guaranteed that the sum of nn over all test cases does not exceed 2105(n2105)2⋅10^5 (∑n≤2⋅10^5).

Output

For each test case, print the answer on it — "YES"(without quotes) if it is possible to make strings ss and tt equal after some (possibly, empty) sequence of moves and "NO"otherwise.

input

4
4
abcd
abdc
5
ababa
baaba
4
asdf
asdg
4
abcd
badc

output

NO
YES
NO
YES

題意

給你兩個字符串 sstt ,長度都是 nn ,都由小寫拉丁字母組成。
在一次移動中,您可以選擇從 11nn 的任意長度 lenlen 並執行以下操作:
選擇長度爲 lenlen 的字符串 ss 的任何相鄰子字符串並將其反轉;
同時選擇 lenlen 長度的字符串 tt 的任何相鄰子字符串,並將其反轉。
注意,在一個移動過程中,正好反轉字符串 ss 的一個子字符串和字符串 tt 的一個子字符串。
還要注意,在 sstt 中反轉的子串的邊界可以不同,唯一的限制是反轉長度相等的子串。例如,如果 len=3len=3n=5n=5 ,則可以反轉 s[13]s[1…3]t[35]s[24]t[3…5]、s[2…4]t[24]t[2…4] ,但不能反轉 s[13]s[1…3]t[12]t[1…2]
你的任務是說在一些(可能是空的)移動序列之後是否可以使字符串 sstt 相等。
——來自百度翻譯

題解

首先要明白兩幾個規律:

  1. aabb 分別挑一段倒置相當於把 aabb 單獨倒置兩次。
  2. 倒置偶數次相同的位置相當於沒有倒置,而且倒置奇數次同一段子串相當於把那一段子串倒置 11 次,所以題目就要求要分別挑兩段不同的子串倒置
  3. 長度爲奇數的倒置可以轉化成奇數次相鄰兩個元素的調換,長度爲偶數的倒置可以轉換成偶數次相鄰元素的調換;例如abc轉化成cba需要 33 次相鄰元素的調換位置 2+1(2+1)abcd轉化成dcba需要 66 次相鄰元素的調換位置 3+2+1(3+2+1) 。那麼題目要求就可以轉化成偶數次相鄰元素的調換位置

那麼現在題目就變成了讓字符串 aa 經過偶數次相鄰元素的調換能不能轉化成字符串 bb

現在還可以先篩選出一些確定的情況:

  1. aa 中的各個元素的個數和 bb 中的不一樣的話是肯定不可能轉換成功的。
  2. aabb 中有某個元素的個數多於一個的話是肯定能轉換成功的。因爲這時可以先把 aa 中的這兩個元素調換在一起,然後就可以反覆調換 aa 中的這兩個元素的位置,而在 bb 字符串中調換其他的元素,那就相當於不斷變換 bb 的位置,那 bb 當然能變換成任意順序,最終達到和 aa 相同。

若此時還沒有判斷出是否可能,那麼此時 aabb 就滿足裏面的每個元素都不同且兩個字符串的元素存在一一對應的關係。

那麼就開始遞推:

aa 中的第一個元素開始,查找 bb 中的對應的元素,假設和 a[i]a[i] 對應的是 b[j]b[j] ,那麼就調換 b[i]b[i]b[j]b[j] 的位置。不過調換前需要判斷 jij-i 是不是偶數,若不是,需要先調換一下 a[i+1]a[i+1]a[i+2]a[i+2] (之所以不能調換 bb 中的元素,是因爲不能確定調換哪兩個對 b[j]b[j] 無影響,若是能找到不影響 b[j]b[j] 的,那也可以,總之調換必須是偶數次就行了),這樣就能使 a[i]a[i]b[i]b[i] 是一樣的。

循環如此,之後就只需要判斷最後兩個是否相同就可以判斷能否轉化了。因爲如果只有最後兩個不同,那麼只有轉換奇數次才能相同。

代碼

#include<bits/stdc++.h>
using namespace std;
const int MAXA = 4e5;
int n, a[MAXA], b[MAXA], tmp, j;
char s1[MAXA], s2[MAXA];
int solve() {
	scanf("%d", &n);
	scanf("%s", s1 + 1);
	scanf("%s", s2 + 1);
	for (int i = 0; i < 26; i++) a[i] = b[i] = 0;
	for (int i = 1; i <= n; i++) {
		a[s1[i] - 'a']++;
		b[s2[i] - 'a']++;
	}
	for (int i = 0; i < 26; i++)
		if (a[i] != b[i]) 
			return printf("NO\n"), 0;

	for (int i = 0; i < 26; i++)
		if (a[i] > 1 || b[i] > 1) 
			return printf("YES\n"), 0;
	if (n == 1) return printf("YES\n"), 0;

	for (int i = 1; i <= n - 2; i++) {
		if (s1[i] == s2[i]) 
			continue;
		for (j = i + 1; j <= n; j++)
			if (s1[i] == s2[j]) 
				break;
		if ((j - i) & 1) swap(s1[i + 1], s1[i + 2]);
		tmp = s2[j];
		for (; j > i; j--)
			s2[j] = s2[j - 1];
		s2[i] = tmp;
	}
	if (s1[n] == s2[n]) 
		printf("YES\n");
	else 
		printf("NO\n");
	return 0;
}
int main() {
	//freopen("in.txt", "r", stdin);
	int t;
	scanf("%d", &t);
	while (t--) 
		solve();
}

發佈了179 篇原創文章 · 獲贊 56 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章