Word matching by swapping and incrementing characters
Last Updated :
24 Nov, 2023
Given two strings A and B, determine if string A can be made equal to string B by performing some operations on string A any number of times. Before starting the operations, we have to choose an integer K > 1. The operations that can be performed on String A are:
- Type 1: Select any index i (0 ≤ i< length(A)-1) and swap(A[i], A[i+1]).
- Type 2: Select a substring of length K where all characters are the same and increase each character to its alphabetically next character, e.g. ‘aa’ → ‘bb’. A substring of ‘z’ cannot be incremented.
Examples:
Input: A = “acbcdd”, B = “abeded”
Output: 1
Explanation: Consider K = 2,
- Apply the 1st operation at index 1, then A =”abccdd”.
- Apply 2nd operation at index 2 twice, then A = “abeedd”.
- Apply 1st operation at index 3, then A = “abeded” which is equal to B.
The two strings are matching.
Input: A = “xyz” ,B= “xxy”
Output: 0
Explanation: It is impossible to convert A to B as string B has more frequency of character ‘x’ and we cannot convert any character (‘y’ or ‘ z’) of string A to character ‘x’.
Input: A = “abcde” ,B= “ab”
Output: 0
Explanation: It is impossible to convert A to B as they both are of different length and no operation can increase or decrease the length of string A.
Approach: To solve the problem follow the below idea:
Verify that both strings have matching character frequencies use hashing to count character frequency disregarding character order. Iterate from K = 2 to K = n, check if string A can be converted to string B by allowing operation 2. If any K yields equality, it’s possible to convert A to B.
Follow the steps to solve the problem:
- Read two strings, ‘a’ and ‘b’.
- If the two strings have different length, print ‘0’.
- Initialize two maps ‘freq_a’ and ‘freq_b’ to record the frequency of each character of string ‘a’ and ‘b’ respectively.
- Determine the maximum possible ‘K’ value, which is equal to the length of ‘a’ or ‘b’.
- Iterate over values from 2 to K, and for each value(K), call the ‘check‘ function to see if it’s possible to convert ‘a’ to ‘b’.
- If ‘check‘ returns true, then we can break the loop as we have found our answer.
- The ‘check’ Function takes an integer ‘K’ as an argument and Iterates through lowercase English alphabet characters from ‘a’ to ‘z’.
- For each character ‘ch’ it compares the character frequencies of ‘ch’ in ‘a’ and ‘b’.
- If ‘f1’ (frequency in ‘a’) is greater than or equal to ‘f2’ (frequency in ‘b’):
- Calculate the frequency difference ‘diff’ between ‘f1’ and ‘f2’ and checks if ‘diff’ is divisible by ‘K’:
- If true, it means Type 1 operation can be used to match characters
- Updates the frequency of the next character (‘ch+1’) in ‘a’.
- Otherwise, returns false.
- If ‘f1’ is less than ‘f2’, returns false.
- If the loop completes without returning false, it means ‘a’ can be converted to ‘b’ using the chosen ‘K’, therefore return true.
Below is the C++ implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
map< char , int > freq_a, freq_b;
bool check( int k)
{
map< char , int > freq_a_copy = freq_a;
for ( char ch = 'a' ; ch <= 'z' ; ch++) {
int f1 = freq_a_copy[ch], f2 = freq_b[ch];
int diff = f1 - f2;
if (diff < 0 || diff % k != 0)
return false ;
freq_a_copy[ch + 1] += diff;
}
return true ;
}
int main()
{
string a = "acbcdd", b = "abeded";
if (a.length() != b.length())
cout << "0";
else {
int len = a.length();
for ( int i = 0; i < len; i++)
freq_a[a[i]]++;
for ( int i = 0; i < len; i++)
freq_b[b[i]]++;
int flag = 0;
for ( int k = 2; k <= len; k++) {
if (check(k)) {
flag = 1;
break ;
}
}
cout << flag;
}
return 0;
}
|
Java
import java.util.HashMap;
import java.util.Map;
public class ConvertStrings {
public static boolean check(String a, String b, int k) {
Map<Character, Integer> freq_a = new HashMap<>();
Map<Character, Integer> freq_b = new HashMap<>();
for ( int i = 0 ; i < a.length(); i++) {
char ch = a.charAt(i);
freq_a.put(ch, freq_a.getOrDefault(ch, 0 ) + 1 );
}
for ( int i = 0 ; i < b.length(); i++) {
char ch = b.charAt(i);
freq_b.put(ch, freq_b.getOrDefault(ch, 0 ) + 1 );
}
for ( char ch = 'a' ; ch <= 'z' ; ch++) {
int f1 = freq_a.getOrDefault(ch, 0 );
int f2 = freq_b.getOrDefault(ch, 0 );
int diff = f1 - f2;
if (diff < 0 || diff % k != 0 ) {
return false ;
}
freq_a.put(( char )(ch + 1 ), freq_a.getOrDefault(( char )(ch + 1 ), 0 ) + diff);
}
return true ;
}
public static void main(String[] args) {
String a = "acbcdd" ;
String b = "abeded" ;
if (a.length() != b.length()) {
System.out.println( "0" );
} else {
int len = a.length();
int flag = 0 ;
for ( int k = 2 ; k <= len; k++) {
if (check(a, b, k)) {
flag = 1 ;
break ;
}
}
System.out.println(flag);
}
}
}
|
Python3
freq_a = {}
freq_b = {}
def check(k):
freq_a_copy = dict (freq_a)
for ch in range ( ord ( 'a' ), ord ( 'z' ) + 1 ):
ch = chr (ch)
f1 = freq_a_copy.get(ch, 0 )
f2 = freq_b.get(ch, 0 )
diff = f1 - f2
if diff < 0 or diff % k ! = 0 :
return False
freq_a_copy[ chr ( ord (ch) + 1 )] = freq_a_copy.get( chr ( ord (ch) + 1 ), 0 ) + diff
return True
if __name__ = = "__main__" :
a = "acbcdd"
b = "abeded"
if len (a) ! = len (b):
print ( "0" )
else :
length = len (a)
for i in range (length):
if a[i] in freq_a:
freq_a[a[i]] + = 1
else :
freq_a[a[i]] = 1
for i in range (length):
if b[i] in freq_b:
freq_b[b[i]] + = 1
else :
freq_b[b[i]] = 1
flag = 0
for k in range ( 2 , length + 1 ):
if check(k):
flag = 1
break
print (flag)
|
C#
using System;
using System.Collections.Generic;
public class GFG {
public static bool Check( string a, string b, int k)
{
Dictionary< char , int > freqA
= new Dictionary< char , int >();
Dictionary< char , int > freqB
= new Dictionary< char , int >();
foreach ( char ch in a)
{
if (freqA.ContainsKey(ch))
freqA[ch]++;
else
freqA[ch] = 1;
}
foreach ( char ch in b)
{
if (freqB.ContainsKey(ch))
freqB[ch]++;
else
freqB[ch] = 1;
}
for ( char ch = 'a' ; ch <= 'z' ; ch++) {
int f1 = freqA.GetValueOrDefault(ch, 0);
int f2 = freqB.GetValueOrDefault(ch, 0);
int diff = f1 - f2;
if (diff < 0 || diff % k != 0) {
return false ;
}
char nextChar = ( char )(ch + 1);
freqA[nextChar]
= freqA.GetValueOrDefault(nextChar, 0)
+ diff;
}
return true ;
}
public static void Main( string [] args)
{
string a = "acbcdd" ;
string b = "abeded" ;
if (a.Length != b.Length) {
Console.WriteLine( "0" );
}
else {
int len = a.Length;
int flag = 0;
for ( int k = 2; k <= len; k++) {
if (Check(a, b, k)) {
flag = 1;
break ;
}
}
Console.WriteLine(flag);
}
}
}
|
Javascript
function nextChar(c) {
return String.fromCharCode(c.charCodeAt(0) + 1);
}
function check(a, b, k) {
const freq_a = new Map();
const freq_b = new Map();
for (let i = 0; i < a.length; i++) {
let ch = a[i];
freq_a.set(ch, (freq_a.get(ch) || 0) + 1);
}
for (let i = 0; i < b.length; i++) {
let ch = b[i];
freq_b.set(ch, (freq_b.get(ch) || 0) + 1);
}
for (let ch = 'a' ; ch <= 'z' ; ch = nextChar(ch)) {
let f1 = freq_a.get(ch) || 0;
let f2 = freq_b.get(ch) || 0;
let diff = f1 - f2;
if (diff < 0 || diff % k !== 0) {
return false ;
}
freq_a.set(nextChar(ch), (freq_a.get(nextChar(ch)) || 0) + diff);
}
return true ;
}
let a = "acbcdd" ;
let b = "abeded" ;
if (a.length != b.length) {
console.log( "0" );
} else {
let len = a.length;
let flag = 0;
for (let k = 2; k <= len; k++) {
if (check(a, b, k)) {
flag = 1;
break ;
}
}
console.log(flag);
}
|
Time Complexity: O(27*|a|), where |a| is the length of the input string ‘a’.
Auxiliary Space: O(1), as we only require maps of fixed size(26).
Share your thoughts in the comments
Please Login to comment...