Convert given string to another by minimum replacements of subsequences by its smallest character
Last Updated :
07 Aug, 2023
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: 2
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 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>
Time Complexity: O(N)
Auxiliary Space: O(N)
Similar Reads
Minimum cost to delete characters from String A to remove any subsequence as String B Given two strings A and B of size N and M respectively, where B is a sub-sequence of A and an array arr[] of size N, where arr[i] is the cost to delete ith character from string A. The task is to find the minimum cost to delete characters from A such that after deletion no subsequence of A is the sa
15+ min read
Lexicographically smallest subsequence possible by removing a character from given string Given a string S of length N, the task is to find the lexicographically smallest subsequence of length (N - 1), i.e. by removing a single character from the given string. Examples: Input: S = "geeksforgeeks"Output: "eeksforgeeks"Explanation: Lexicographically smallest subsequence possible is "eeksfo
8 min read
Make a given Binary String non-decreasing by removing the smallest subsequence Given a binary string str of size N, the task is to find the length of the smallest subsequence such that after erasing the subsequence the resulting string will be the longest continuous non-decreasing string. Example : Input: str = "10011"Output: 1Explanation: Removal of the first occurrence of '1
8 min read
Check if String T can be made Substring of S by replacing given characters Given two strings S and T and a 2D array replace[][], where replace[i] = {oldChar, newChar} represents that the character oldChar of T is replaced with newChar. The task is to find if it is possible to make string T a substring of S by replacing characters according to the replace array. Note: Each
9 min read
Minimum characters to be replaced in given String to make all characters same Given a string str of size N consisting of lowercase English characters, the task is to find the minimum characters to be replaced to make all characters of string str same. Any character can be replaced by any other character. Example: Input: str="geeksforgeeks"Output: 9Explanation: Replace all the
7 min read
Minimize removals to remove another string as a subsequence of a given string Given two strings str and X of length N and M respectively, the task is to find the minimum characters required to be removed from the string str such that string str doesn't contain the string X as a subsequence. Examples: Input: str = "btagd", X = "bad"Output: 1Explanation:String "btag" has does n
14 min read