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

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



filter_none

edit
close

play_arrow

link
brightness_4
code

// 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; 
chevron_right

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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 
chevron_right

filter_none

edit
close

play_arrow

link
brightness_4
code

# 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
chevron_right

Output: 
2

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

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.




Recommended Posts:


Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.



Improved By : offbeat, dadimadhav

Article Tags :
Practice Tags :