Strings A and B are K-similar (for some non-negative integer K) if we can swap the positions of two letters in A exactly K times so that the resulting string equals B.
Given two anagrams A and B, return the smallest K for which A and B are K-similar.
Example 1:
Input: A = "ab", B = "ba"
Output: 1
Example 2:
Input: A = "abc", B = "bca"
Output: 2
Example 3:
Input: A = "abac", B = "baca"
Output: 2
Example 4:
Input: A = "aabc", B = "abca"
Output: 2
Note:
1 <= A.length == B.length <= 20
A and B contain only lowercase letters from the set {'a', 'b', 'c', 'd', 'e', 'f'}
// BFS
int kSimilarity(string A, string B) {
if (A == B) return 0;
int res = 0, len = A.length();
queue<string> q({A});
unordered_set<string> visited({A});
while (!q.empty()) {
++res;
for (int k = q.size() - 1; k >= 0; --k) {
string str = q.front(); q.pop();
int i = 0;
while (str[i] == B[i]) ++i;
for (int j = i + 1; j < len; ++j) {
if (str[j] == B[j] || str[i] != B[j]) continue; // Skip already sorted or unmatched
swap(str[i], str[j]);
if (str == B) return res;
if (!visited.count(str)) {
q.push(str);
visited.insert(str);
}
swap(str[i], str[j]); // reset
}
}
}
return res;
}
// DFS Backtracking
int backtracking(string& A, const string& B, unordered_map<string, int>& mp, int i) {
if (A == B) return 0;
if (mp.count(A)) return mp[A];
int res = INT_MAX;
while (i < A.length() && A[i] == B[i]) ++i;
for (int j = i + 1; j < A.length(); ++j) {
if (A[j] == B[i]) {
swap(A[i], A[j]);
int next = backtracking(A, B, mp, i + 1);
if (next != INT_MAX) {
res = min(res, next + 1);
}
swap(A[i], A[j]);
}
}
mp[A] = res;
return res;
}
int kSimilarity(string A, string B) {
unordered_map<string, int> mp;
return backtracking(A, B, mp, 0);
}