Skip to content
Related Articles
Get the best out of our app
GeeksforGeeks App
Open App
geeksforgeeks
Browser
Continue

Related Articles

Convert given string to another by minimum replacements of subsequences by its smallest character

Improve Article
Save Article
Like Article
Improve Article
Save Article
Like Article

Given two strings A and B, the task is to count the minimum number of operations required to convert the string A to B. In one operation, select a subsequence from string A and convert every character of that subsequence to the smallest character present in it. If it is not possible to transform, then print “-1”.

Examples:

Input: A = “abcab”, B = “aabab” 
Output:
Explanation: 
Operation 1: Replacing characters from indices {2, 1} by the smallest character from those indices(i.e. ‘b’), transforms A to “abbab”. 
Operation 2: Replacing characters from indices {1, 0}, by the smallest character from those indices(i.e. ‘a’), transforms A to “aabab”. 
Therefore, the count of operations required to convert string A to B is 2.

Input: A = “aaa”, B = “aab” 
Output: -1 
Explanation: 
There is no possible way to convert A to B as string A doesn’t contain ‘b’.

Approach: The approach is based on the idea that if any character at index i of string A is less than the character at index i of string B, then it is impossible to change A to B because changing a character to a character smaller than itself is not allowed. Below are the steps:

  1. Initialize two array of vectors convChar and str1array, of size 26. Each index of these arrays corresponds to a character.
  2. The ith index of convChar contains indices of string A that should be converted to the ith alphabet and str1array contains the indices of all characters of string A.
  3. Initialize a Hashmap convertMap that indicates the particular character to which the character at index i of string A should be converted to.
  4. Iterate over both strings simultaneously, three possible cases can occur: 
    • If ith character of string A is less than ith character of string B, then it is impossible to change A to B. Therefore, print “-1”.
    • If both characters on the current index are same then it requires no change.
    • Otherwise, insert this index i in convChar array on the index corresponding to the ith character of string B and insert the character value of ith character in string B in the Hashmap convertMap with the key value as i.
  5. Initialize the a variable ret that counts the minimum operations required and a vector retV to store the set of operations.
  6. Now iterate over all the alphabets in reverse order. Do the following steps in each iteration:
    • Check for each alphabet, if there is at least one index that should be converted to the current alphabet.
    • Increase ret by one to count the required number of steps. Let v be the vector of indices that should be converted to the current alphabet with index i and v1 be the vector that contains all the indices of string A. Then two cases can occur:
      1. If v1 has no element, then current alphabet is not present in string A. Therefore, it is not possible to change A to B.
      2. Otherwise, proceed to next step.
    • Iterate for each index j of vector v1. In this iteration, search for the minimum index to include in the set S
      1. If jth alphabet of vector v1 is present in convertMap, it means that this alphabet has been converted or will convert to another character in an operation. If it has been converted in one of previous operations, then proceed to next iteration of v1.
      2. Else add this index in the set. And come out of the loop
    • If any such index j is not found in vector v1, then it is impossible to convert string A to B. Hence print “-1”

Below is the implementation of the above approach:

C++




// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to return the minimum number
// of operation
void transformString(string str1,
                    string str2)
{
    // Storing data
    int N = str1.length();
 
    vector<int> convChar[26];
    vector<int> str1array[26];
 
    // Initialize both arrays
    for (int i = 0; i < 26; i++) {
        vector<int> v;
        convChar[i] = v;
        str1array[i] = v;
    }
 
    // Stores the index of character
    map<int, char> convertMap;
 
    // Filling str1array, convChar
    // and hashmap convertMap.
    for (int i = 0; i < N; i++) {
        str1array[str1[i] - 'a'].push_back(i);
    }
 
    for (int i = 0; i < N; i++) {
 
        // Not possible to convert
        if (str1[i] < str2[i]) {
            cout << -1 << endl;
            return;
        }
        else if (str1[i] == str2[i])
            continue;
        else {
            convChar[str2[i] - 'a'].push_back(i);
            convertMap[i] = str2[i];
        }
    }
 
    // Calculate result
    // Initializing return values
    int ret = 0;
    vector<vector<int> > retv;
 
    // Iterating the character from
    // the end
    for (int i = 25; i >= 0; i--) {
 
        vector<int> v = convChar[i];
 
        if (v.size() == 0)
            continue;
 
        // Increment the number of
        // operations
        ret++;
        vector<int> v1 = str1array[i];
 
        // Not possible to convert
        if (v1.size() == 0) {
            cout << -1 << endl;
            return;
        }
 
        // to check whether the final
        // element has been added
        // in set S or not.
        bool isScompleted = false;
 
        for (int j = 0; j < v1.size(); j++) {
 
            // Check if v1[j] is present
            // in hashmap or not
            if (convertMap.find(v1[j])
                != convertMap.end()) {
 
                char a = convertMap[v1[j]];
 
                // Already converted then
                // then continue
                if (a > i + 'a')
                    continue;
                else {
                    v.push_back(v1[j]);
                    isScompleted = true;
                    retv.push_back(v);
                    break;
                }
            }
            else {
                v.push_back(v1[j]);
                isScompleted = true;
                retv.push_back(v);
                break;
            }
        }
 
        // Not possible to convert
        if (!isScompleted) {
            cout << -1 << endl;
            return;
        }
    }
 
    // Print the result
    cout << ret << endl;
}
 
// Driver Code
int main()
{
    // Given strings
    string A = "abcab";
    string B = "aabab";
 
    // Function Call
    transformString(A, B);
    return 0;
}

Java




// Java program for the above approach
import java.util.*;
import java.lang.*;
 
class GFG{
 
// Function to return the minimum number
// of operation
static void transformString(String str1,
                            String str2)
{
    // Storing data
    int N = str1.length();
    ArrayList<
    ArrayList<Integer>> convChar = new ArrayList<>();
    ArrayList<
    ArrayList<Integer>> str1array = new ArrayList<>();
 
    // Initialize both arrays
    for(int i = 0; i < 26; i++)
    {
        convChar.add(new ArrayList<>());
        str1array.add(new ArrayList<>());
    }
 
    // Stores the index of character
    Map<Integer,
        Character> convertMap = new HashMap<>();
 
    // Filling str1array, convChar
    // and hashmap convertMap.
    for(int i = 0; i < N; i++)
    {
        str1array.get(str1.charAt(i) - 'a').add(i);
    }
 
    for(int i = 0; i < N; i++)
    {
         
        // Not possible to convert
        if (str1.charAt(i) < str2.charAt(i))
        {
            System.out.println(-1);
            return;
        }
        else if (str1.charAt(i) == str2.charAt(i))
            continue;
        else
        {
            convChar.get(str2.charAt(i) - 'a').add(i);
            convertMap.put(i,str2.charAt(i));
        }
    }
 
    // Calculate result
    // Initializing return values
    int ret = 0;
    ArrayList<
    ArrayList<Integer>> retv = new ArrayList<>();
 
    // Iterating the character from
    // the end
    for(int i = 25; i >= 0; i--)
    {
        ArrayList<Integer> v = convChar.get(i);
 
        if (v.size() == 0)
            continue;
 
        // Increment the number of
        // operations
        ret++;
        ArrayList<Integer> v1 = str1array.get(i);
 
        // Not possible to convert
        if (v1.size() == 0)
        {
            System.out.println(-1);
            return;
        }
 
        // To check whether the final
        // element has been added
        // in set S or not.
        boolean isScompleted = false;
 
        for(int j = 0; j < v1.size(); j++)
        {
             
            // Check if v1[j] is present
            // in hashmap or not
            if (convertMap.containsKey(v1.get(j)))
            {
                char a = convertMap.get(v1.get(j));
 
                // Already converted then
                // then continue
                if (a > i + 'a')
                    continue;
                else
                {
                    v.add(v1.get(j));
                    isScompleted = true;
                    retv.add(v);
                    break;
                }
            }
            else
            {
                v.add(v1.get(j));
                isScompleted = true;
                retv.add(v);
                break;
            }
        }
 
        // Not possible to convert
        if (!isScompleted)
        {
            System.out.println(-1);
            return;
        }
    }
 
    // Print the result
    System.out.println(ret);
}
 
// Driver Code
public static void main (String[] args)
{
     
    // Given strings
    String A = "abcab";
    String B = "aabab";
     
    // Function call
    transformString(A, B);
}
}
 
// This code is contributed by offbeat

Python3




# Python3 program for the above approach
 
# Function to return the minimum number
# of operation
def transformString(str1, str2):
     
    # Storing data
    N = len(str1)
    convChar = []
    str1array = []
     
    # Initialize both arrays
    for i in range(26):
        convChar.append([])
        str1array.append([])
         
    # Stores the index of character
    convertMap = {}
     
    # Filling str1array, convChar
    # and hashmap convertMap.
    for i in range(N):
        str1array[ord(str1[i]) -
                  ord('a')].append(i)
         
    for i in range(N):
         
        # Not possible to convert
        if (str1[i] < str2[i]):
            print(-1)
            return
        elif (str1[i] == str2[i]):
            continue
        else:
            convChar[ord(str2[i]) -
                     ord('a')].append(i)
            convertMap[i] = str2[i]
     
    # Calculate result
    # Initializing return values
    ret = 0
    retv = []
     
    # Iterating the character from
    # the end
    for i in range(25, -1, -1):
        v = convChar[i]
         
        if (len(v) == 0):
            continue
         
        # Increment the number of
        # operations
        ret += 1;
        v1 = str1array[i]
         
        # Not possible to convert
        if (len(v1) == 0):
            print(-1)
            return
         
        # To check whether the final
        # element has been added
        # in set S or not.
        isScompleted = False
         
        for j in range(len(v1)):
             
            # Check if v1[j] is present
            # in hashmap or not
            if (v1[j] in convertMap):
                a = v1[j]
                 
                # Already converted then
                # then continue
                if (a > i + ord('a')):
                    continue
                else:
                    v.append(v1[j])
                    isScompleted = True
                    retv.append(v)
                    break
            else:
                v.append(v1[j])
                isScompleted = True
                retv.append(v)
                break
         
        # Not possible to convert
        if (isScompleted == False):
            print(-1)
            return
     
    # Print the result
    print(ret)
             
# Driver Code
A = "abcab"
B = "aabab"
 
# Function call
transformString(A, B)
 
# This code is contributed by dadi madhav

C#




// C# program for the above approach 
using System;
using System.Collections.Generic;
 
class GFG{
     
// Function to return the minimum number 
// of operation 
static void transformString(string str1, string str2) 
{
     
    // Storing data 
    int N = str1.Length; 
    List<List<int>> convChar = new List<List<int>>(); 
    List<List<int>> str1array = new List<List<int>>(); 
   
    // Initialize both arrays 
    for(int i = 0; i < 26; i++) 
    
        convChar.Add(new List<int>()); 
        str1array.Add(new List<int>()); 
    
   
    // Stores the index of character 
    Dictionary<int,
               char> convertMap = new Dictionary<int,
                                                 char>(); 
   
    // Filling str1array, convChar 
    // and hashmap convertMap. 
    for(int i = 0; i < N; i++) 
    
        str1array[str1[i] - 'a'].Add(i); 
    
   
    for(int i = 0; i < N; i++) 
    
         
        // Not possible to convert 
        if (str1[i] < str2[i]) 
        
            Console.WriteLine(-1); 
            return
        
        else if (str1[i] == str2[i]) 
            continue
        else
        
            convChar[str2[i] - 'a'].Add(i); 
            convertMap[i] = str2[i]; 
        
    
   
    // Calculate result 
    // Initializing return values 
    int ret = 0; 
    List<List<int>> retv = new List<List<int>>(); 
   
    // Iterating the character from 
    // the end 
    for(int i = 25; i >= 0; i--) 
    
        List<int> v = convChar[i]; 
   
        if (v.Count == 0) 
            continue
   
        // Increment the number of 
        // operations 
        ret++; 
        List<int> v1 = str1array[i]; 
   
        // Not possible to convert 
        if (v1.Count == 0) 
        
            Console.WriteLine(-1); 
            return
        
   
        // To check whether the final 
        // element has been added 
        // in set S or not. 
        bool isScompleted = false
   
        for(int j = 0; j < v1.Count; j++) 
        
             
            // Check if v1[j] is present 
            // in hashmap or not 
            if (convertMap.ContainsKey(v1[j])) 
            
                char a = convertMap[v1[j]]; 
   
                // Already converted then 
                // then continue 
                if (a > i + 'a'
                    continue
                else
                
                    v.Add(v1[j]); 
                    isScompleted = true
                    retv.Add(v); 
                    break
                
            
            else
            
                v.Add(v1[j]); 
                isScompleted = true
                retv.Add(v); 
                break
            
        
   
        // Not possible to convert 
        if (!isScompleted) 
        
            Console.WriteLine(-1); 
            return
        
    
   
    // Print the result 
    Console.WriteLine(ret); 
}
 
// Driver code
static void Main()
{
    // Given strings 
    string A = "abcab"
    string B = "aabab"
       
    // Function call 
    transformString(A, B);
}
}
 
// This code is contributed by divyesh072019

Javascript




<script>
 
// JavaScript program for the above approach
 
// Function to return the minimum number
// of operation
function transformString(str1, str2)
{
     
    // Storing data
    let N = str1.length
    let convChar = []
    let str1array = []
     
    // Initialize both arrays
    for(let i = 0; i < 26; i++)
    {
        convChar.push([])
        str1array.push([])
    }
         
    // Stores the index of character
    let convertMap = new Map()
     
    // Filling str1array, convChar
    // and hashmap convertMap.
    for(let i = 0; i < N; i++)
    {
        str1array[str1.charCodeAt(i) - 'a'.charCodeAt(0)].push(i)
    }
         
    for(let i = 0; i < N; i++)
    {
         
        // Not possible to convert
        if (str1.charCodeAt(i) < str2.charCodeAt(i))
        {
            document.write(-1)
            return
        }
        else if (str1[i] == str2[i])
            continue
        else
            convChar[str2.charCodeAt(i) - 'a'.charCodeAt(0)].push(i)
            convertMap[i] = str2[i]
    }
     
    // Calculate result
    // Initializing return values
    let ret = 0
    let retv = []
     
    // Iterating the character from
    // the end
    for(let i = 25; i >= 0; i--)
    {
        let v = convChar[i]
         
        if (v.length == 0)
            continue
         
        // Increment the number of
        // operations
        ret += 1;
        v1 = str1array[i]
         
        // Not possible to convert
        if (v1.length == 0){
            document.write(-1)
            return
        }
         
        // To check whether the final
        // element has been added
        // in set S or not.
        isScompleted = false
         
        for(let j = 0; j < v1.length; j++)
        {
             
            // Check if v1[j] is present
            // in hashmap or not
            if (convertMap.has(v1[j])){
                let a = v1[j]
                 
                // Already converted then
                // then continue
                if (a > i + 'a'.charCodeAt(0))
                    continue
                else{
                    v.push(v1[j])
                    isScompleted = true
                    retv.append(v)
                    break
                }
            }
            else{
                v.push(v1[j])
                isScompleted = true
                retv.push(v)
                break
            }
        }
         
        // Not possible to convert
        if (isScompleted == false){
            document.write(-1)
            return
        }
    }
     
    // Print the result
    document.write(ret)
}
             
// Driver Code
let A = "abcab"
let B = "aabab"
 
// Function call
transformString(A, B)
 
// This code is contributed by shinjanpatra
 
</script>

Output: 

2

Time Complexity: O(N) 
Auxiliary Space: O(N)
 


My Personal Notes arrow_drop_up
Last Updated : 28 Mar, 2022
Like Article
Save Article
Similar Reads
Related Tutorials