Open In App

Transforming Strings with Alphabetical Shifts

Last Updated : 12 Jan, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Given two strings S1 and S2 and a positive integer K, the task is to check if it’s possible to change S1 into S2 by performing the given operation at most K times. In ith operation, 1 <= i <= K, you may choose an unused character in S1 and replace it with the letter i positions ahead in the English alphabet.

Note: The increment is cyclic, meaning that incrementing ‘z‘ by 1 results in the character ‘a

Examples:

Input: A = “gcbksforgeeks”, B = “geeksforgeeks”, N = 3
Output: True
Explanation: In the 2nd operation, we shift ‘c’ at 1st index 2 times to get ‘e’. And in the 3rd operation, we shift ‘d’ at index 2 to get ‘e’.

Input: A = “cccb”, B = “ccca”, N = 25
Output: True
Explanation: In the 25th operation, we shift ‘b’ at index 3 to ‘a’.

Transforming Strings with Alphabetical Shifts using Hashing:

Each letter can be shifted only once, and no two letters can be shifted by the same number of positions i. In other words, if we shift one letter by 2, no other letters can be shifted by 2. If we need to shift by 2 again, you need to use “wrapping” and shift by 28 (which is 2 + 26).

Step-by-step approach:

  • If the sizes of both strings are not equal, return false.
  • Initialize an array arr[] of size 26 to track character shifts.
  • Iterate over string S1.
    • Calculate the increment needed to match S1[i] with S2[i].
    • Calculate the total operations needed for characters with the same increment.
    • If total operations exceed K, return false.
    • Increment arr for the required shift.
  • Return true.

Below is the implementation of the above approach:

C++




// C++ code to implement the approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Functio to check if conversion is possible
bool canConvert(string S1, string S2, int K)
{
    // Check if size of both strings are
    // not equal If true, return false;
    if (S1.size() != S2.size())
        return false;
 
    // Intilize an array of size 26
    // where, arr[i] = x implies that
    // there are x characters in string S1
    // that need S1 shift of i times to
    // match the charcters in string S2.
    vector<int> arr(26, 0);
 
    // Iterate over the string S1.
    for (int i = 0; i < S1.size(); i++) {
 
        // Calculate the increment needed to
        // convert S1[i] to S2[i]
        int shift = (S2[i] - S1[i] + 26) % 26;
 
        // Calculate the total operations
        // require to increment all elements
        // requiring same number of increment.
        // If total operation required is
        // greater than K, return false
        if (shift != 0 && shift + arr[shift] * 26 > K)
            return false;
 
        // Increment the frequency of
        // shift in array arr
        arr[shift]++;
    }
 
    // Finally, return true
    return true;
}
 
// Driver code
int main()
{
    string S1 = "gcbksforgeeks", S2 = "geeksforgeeks";
    int K = 3;
 
    // Function Call
    if (canConvert(S1, S2, K))
        cout << "True";
    else
        cout << "False";
 
    return 0;
}


Java




import java.util.*;
public class Solution {
 
    // Function to check if conversion is possible
    static boolean canConvert(String S1, String S2, int K)
    {
        // Check if the size of both strings is not equal.
        // If true, return false;
        if (S1.length() != S2.length()) {
            return false;
        }
 
        // Initialize an array of size 26
        // where arr[i] = x implies that
        // there are x characters in string S1
        // that need S1 shift of i times to
        // match the characters in string S2.
        int[] arr = new int[26];
 
        // Iterate over the string S1.
        for (int i = 0; i < S1.length(); i++) {
            // Calculate the increment needed to
            // convert S1[i] to S2[i]
            int shift
                = (S2.charAt(i) - S1.charAt(i) + 26) % 26;
 
            // Calculate the total operations
            // required to increment all elements
            // requiring the same number of increments.
            // If the total operation required is
            // greater than K, return false
            if (shift != 0 && shift + arr[shift] * 26 > K) {
                return false;
            }
 
            // Increment the frequency of
            // shift in array arr
            arr[shift]++;
        }
 
        // Finally, return true
        return true;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        String S1 = "gcbksforgeeks", S2 = "geeksforgeeks";
        int K = 3;
 
        // Function Call
        if (canConvert(S1, S2, K)) {
            System.out.println("True");
        }
        else {
            System.out.println("False");
        }
    }
}


Python3




# Python Implementation
def can_convert(S1, S2, K):
    # Check if size of both strings are not equal
    # If true, return False
    if len(S1) != len(S2):
        return False
 
    # Initialize a list of size 26
    # where, arr[i] = x implies that
    # there are x characters in string S1
    # that need S1 shift of i times to
    # match the characters in string S2.
    arr = [0] * 26
 
    # Iterate over the string S1.
    for i in range(len(S1)):
        # Calculate the increment needed to
        # convert S1[i] to S2[i]
        shift = (ord(S2[i]) - ord(S1[i]) + 26) % 26
 
        # Calculate the total operations
        # required to increment all elements
        # requiring the same number of increments.
        # If the total operations required is
        # greater than K, return False
        if shift != 0 and shift + arr[shift] * 26 > K:
            return False
 
        # Increment the frequency of shift in the arr list
        arr[shift] += 1
 
    # Finally, return True
    return True
 
# Driver code
S1 = "gcbksforgeeks"
S2 = "geeksforgeeks"
K = 3
 
# Function call
if can_convert(S1, S2, K):
    print("True")
else:
    print("False")
     
# This code is contributed by Tapesh(tapeshdua420)


C#




using System;
 
public class Solution {
    // Function to check if conversion is possible
    static bool CanConvert(string S1, string S2, int K)
    {
        // Check if the size of both strings is not equal.
        // If true, return false;
        if (S1.Length != S2.Length)
            return false;
 
        // Initialize an array of size 26
        // where arr[i] = x implies that
        // there are x characters in string S1
        // that need S1 shift of i times to
        // match the characters in string S2.
        int[] arr = new int[26];
 
        // Iterate over the string S1.
        for (int i = 0; i < S1.Length; i++) {
            // Calculate the increment needed to
            // convert S1[i] to S2[i]
            int shift = (S2[i] - S1[i] + 26) % 26;
 
            // Calculate the total operations
            // required to increment all elements
            // requiring the same number of increments.
            // If the total operation required is
            // greater than K, return false
            if (shift != 0 && shift + arr[shift] * 26 > K)
                return false;
 
            // Increment the frequency of
            // shift in array arr
            arr[shift]++;
        }
 
        // Finally, return true
        return true;
    }
 
    // Driver code
    public static void Main(string[] args)
    {
        string S1 = "gcbksforgeeks", S2 = "geeksforgeeks";
        int K = 3;
 
        // Function Call
        if (CanConvert(S1, S2, K))
            Console.WriteLine("True");
        else
            Console.WriteLine("False");
    }
}


Javascript




function canConvert(S1, S2, K) {
    // Check if the size of both strings is not equal
    // If true, return false
    if (S1.length !== S2.length) {
        return false;
    }
 
    // Initialize an array of size 26
    // where arr[i] = x implies that
    // there are x characters in string S1
    // that need S1 shift of i times to
    // match the characters in string S2.
    const arr = Array(26).fill(0);
 
    // Iterate over the string S1.
    for (let i = 0; i < S1.length; i++) {
        // Calculate the increment needed to
        // convert S1[i] to S2[i]
        const shift = (S2.charCodeAt(i) - S1.charCodeAt(i) + 26) % 26;
 
        // Calculate the total operations
        // required to increment all elements
        // requiring the same number of increments.
        // If the total operations required is
        // greater than K, return false
        if (shift !== 0 && shift + arr[shift] * 26 > K) {
            return false;
        }
 
        // Increment the frequency of shift in the arr list
        arr[shift] += 1;
    }
 
    // Finally, return true
    return true;
}
 
// Driver code
const S1 = "gcbksforgeeks";
const S2 = "geeksforgeeks";
const K = 3;
 
// Function call
if (canConvert(S1, S2, K)) {
    console.log("True");
} else {
    console.log("False");
}


Output

True







Time Complexity: O(size(S1))
Auxiliary Space: O(1)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads