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
Smallest string which not a subsequence of the given string Given a string str, consisting of lowercase alphabets, the task is to find the shortest string which is not a subsequence of the given string. If multiple strings exist, then print any one of them. Examples: Input: str = "abaabcc" Output: d Explanation: One of the possible shortest string which is n
6 min read
Lexicographically smallest permutation of a string that contains all substrings of another string Given two strings A and B, the task is to find lexicographically the smallest permutation of string B such that it contains every substring from the string A as its substring. Print â-1â if no such valid arrangement is possible.Examples: Input: A = "aa", B = "ababab" Output: aaabbb Explanation: All
10 min read
Reduce the string to minimum length with the given operation Given a string str consisting of lowercase and uppercase characters, the task is to find the minimum possible length the string can be reduced to after performing the given operation any number of times. In a single operation, any two consecutive characters can be removed if they represent the same
6 min read
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