Open In App

Word matching by swapping and incrementing characters

Last Updated : 24 Nov, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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++




// C++ code for the above approach:
#include <bits/stdc++.h>
using namespace std;
 
// Maps to store frequencies of strings
// 'a' and 'b'
map<char, int> freq_a, freq_b;
 
// Function to check if it's possible to
// convert 'a' to 'b' with a given 'k'
bool check(int k)
{
 
    // Create a copy of the freq_a map
    map<char, int> freq_a_copy = freq_a;
 
    // Loop through all lowercase
    // English alphabets
    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;
 
        // If the frequency of ch in string a
        // is greater than frequency of ch
        // in string b, then convert extra
        // ch characters to ch+1
        freq_a_copy[ch + 1] += diff;
    }
 
    // If the loop completes, it's possible
    // to convert 'a' to 'b' with 'k'
    return true;
}
 
// Drivers code
int main()
{
    string a = "acbcdd", b = "abeded";
 
    if (a.length() != b.length())
        cout << "0";
    else {
        int len = a.length();
 
        // Calculate character frequencies for 'a'
        for (int i = 0; i < len; i++)
            freq_a[a[i]]++;
 
        // Calculate character frequencies for 'b'
        for (int i = 0; i < len; i++)
            freq_b[b[i]]++;
 
        int flag = 0;
 
        // Iterate through 'k' values from 2 to len
        for (int k = 2; k <= len; k++) {
 
            // Check if 'a' can be converted
            // to 'b' with 'k'
            if (check(k)) {
                flag = 1;
                break;
            }
        }
        cout << flag;
    }
    return 0;
}


Java




// Java Implementation
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<>();
         
        // Calculate character frequencies for 'a'
        for (int i = 0; i < a.length(); i++) {
            char ch = a.charAt(i);
            freq_a.put(ch, freq_a.getOrDefault(ch, 0) + 1);
        }
         
        // Calculate character frequencies for 'b'
        for (int i = 0; i < b.length(); i++) {
            char ch = b.charAt(i);
            freq_b.put(ch, freq_b.getOrDefault(ch, 0) + 1);
        }
         
        // Loop through all lowercase English alphabets
        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;
            }
             
            // If the frequency of ch in string a is greater than frequency of ch in string b,
            // then convert extra ch characters to ch+1
            freq_a.put((char)(ch + 1), freq_a.getOrDefault((char)(ch + 1), 0) + diff);
        }
         
        // If the loop completes, it's possible to convert 'a' to 'b' with 'k'
        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;
             
            // Iterate through 'k' values from 2 to len
            for (int k = 2; k <= len; k++) {
                // Check if 'a' can be converted to 'b' with 'k'
                if (check(a, b, k)) {
                    flag = 1;
                    break;
                }
            }
             
            System.out.println(flag);
        }
    }
}
// This code is contributed by Sakshi


Python3




# Python code for the above approach:
 
# Maps to store frequencies of strings 'a' and 'b'
freq_a = {}
freq_b = {}
 
# Function to check if it's possible to convert 'a' to 'b' with a given 'k'
def check(k):
    # Create a copy of the freq_a dictionary
    freq_a_copy = dict(freq_a)
 
    # Loop through all lowercase English alphabets
    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
 
        # If the frequency of ch in string a
        # is greater than the frequency of ch in string b,
        # then convert extra ch characters to ch+1
        freq_a_copy[chr(ord(ch) + 1)] = freq_a_copy.get(chr(ord(ch) + 1), 0) + diff
 
    # If the loop completes, it's possible to convert 'a' to 'b' with 'k'
    return True
 
# Driver's code
if __name__ == "__main__":
    a = "acbcdd"
    b = "abeded"
 
    if len(a) != len(b):
        print("0")
    else:
        length = len(a)
 
        # Calculate character frequencies for 'a'
        for i in range(length):
            if a[i] in freq_a:
                freq_a[a[i]] += 1
            else:
                freq_a[a[i]] = 1
 
        # Calculate character frequencies for 'b'
        for i in range(length):
            if b[i] in freq_b:
                freq_b[b[i]] += 1
            else:
                freq_b[b[i]] = 1
 
        flag = 0
 
        # Iterate through 'k' values from 2 to len
        for k in range(2, length + 1):
            # Check if 'a' can be converted to 'b' with 'k'
            if check(k):
                flag = 1
                break
 
        print(flag)


C#




// C# code for the above approach
 
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>();
 
        // Calculate character frequencies for 'a'
        foreach(char ch in a)
        {
            if (freqA.ContainsKey(ch))
                freqA[ch]++;
            else
                freqA[ch] = 1;
        }
 
        // Calculate character frequencies for 'b'
        foreach(char ch in b)
        {
            if (freqB.ContainsKey(ch))
                freqB[ch]++;
            else
                freqB[ch] = 1;
        }
 
        // Loop through all lowercase English alphabets
        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;
            }
 
            // If the frequency of ch in string a is greater
            // than frequency of ch in string b, then
            // convert extra ch characters to ch+1
            char nextChar = (char)(ch + 1);
            freqA[nextChar]
                = freqA.GetValueOrDefault(nextChar, 0)
                  + diff;
        }
 
        // If the loop completes, it's possible to convert
        // 'a' to 'b' with 'k'
        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;
 
            // Iterate through 'k' values from 2 to len
            for (int k = 2; k <= len; k++) {
                // Check if 'a' can be converted to 'b' with
                // 'k'
                if (Check(a, b, k)) {
                    flag = 1;
                    break;
                }
            }
 
            Console.WriteLine(flag);
        }
    }
}
 
// This code is contributed by ragul21


Javascript




// Javascript code for the above approach
 
// utility function to get the next character
// of a char using its charcode
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();
 
    // Calculate character frequencies for 'a'
    for (let i = 0; i < a.length; i++) {
        let ch = a[i];
        freq_a.set(ch, (freq_a.get(ch) || 0) + 1);
    }
 
    // Calculate character frequencies for 'b'
    for (let i = 0; i < b.length; i++) {
        let ch = b[i];
        freq_b.set(ch, (freq_b.get(ch) || 0) + 1);
    }
 
    // Loop through all lowercase English alphabets
    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;
        }
 
        // If the frequency of ch in string a is greater than frequency of ch in string b,
        // then convert extra ch characters to ch+1
        freq_a.set(nextChar(ch), (freq_a.get(nextChar(ch)) || 0) + diff);
    }
 
    // If the loop completes, it's possible to convert 'a' to 'b' with 'k'
    return true;
}
 
//Driver code
let a = "acbcdd";
let b = "abeded";
 
if (a.length != b.length) {
    console.log("0");
} else {
    let len = a.length;
    let flag = 0;
 
    // Iterate through 'k' values from 2 to len
    for (let k = 2; k <= len; k++) {
        // Check if 'a' can be converted to 'b' with 'k'
        if (check(a, b, k)) {
            flag = 1;
            break;
        }
    }
 
    console.log(flag);
}
 
// This code is contributed by ragul21


Output

1






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).



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads