Given two strings source and target of equal length, and two positive integers, maxCost, and conversionCost, the task is to find the indices of the longest substring in source that can be converted into the same substring in target with a cost less than or equal to maxCost, where each character conversion having a cost of conversionCost units.
Note: If multiple valid substrings exist, return any one of them.
Examples:
Input: source = “abcd”, target = “bcdf”, conversionCost = 1, maxCost = 3
Output: 0 2
Explanation: The substring of source from index 0 to 2 is “abc” which can change to “bcd” in target. The cost of changing would be 3 <= maxCost. And the maximum length possible is 3.Input: source = “adcf”, target = “cdef”, conversionCost = 3, maxCost = 5
Output: 1 3
Finding Longest Substring Conversion using Binary Search:
The idea is to use binary search on answer to find the maximum possible length, and for each length, check its possible to change within maxCost and based on that update the search space of answer and keep track of indices of start and end position of valid substring.
Step-by-step approach:
- Initialize low to 1 and high to the string’s length.
- Initialize result to store the maximum length of a valid substring.
-
While low is less than high, do the following:
- Calculate mid = (start + end) / 2
- Check if mid is a possible length for a valid substring.
- If valid, update result to mid and shift low to mid + 1.
- Otherwise, shift high to mid.
- If a valid substring is found, print its starting and ending indices.
Below is the implementation of the above approach.
#include <bits/stdc++.h> using namespace std;
// Initilise source variable startPos // and endPos for storing the starting // and ending position of valid // substring respectively. int startPos = -1, endPos = -1;
// Function to check if a substring // of a given length is a // valid substring. bool isValid( int len, string& s, string& t,
int conversionCost, int maxCost)
{ int start = 0, end = 0, n = s.size();
int currCost = 0;
while (end < n) {
// Increment the current
// cost if characters are
// different.
if (s[end] != t[end]) {
currCost += conversionCost;
}
// If the substring length matches
// the given length.
if (end - start + 1 == len) {
// Check if the cost is within
// the maximum cost.
if (currCost <= maxCost) {
// Update the starting position
// of the valid substring.
startPos = start;
// Update the ending position
// of the valid substring.
endPos = end;
// Return true as this is a
// valid substring.
return true ;
}
// Subtract the cost
// if the first
// character of the
// previous substring
// was different.
if (s[start] != t[start]) {
currCost -= conversionCost;
}
// Move the start of the substring.
start++;
// Move the end of the substring.
end++;
}
// Increment the end position of the
// substring.
else {
end++;
}
}
// If no valid substring is found,
// return false.
return false ;
} void validSubstring(string source, string target,
int conversionCost, int maxCost)
{ // Initilise source variable low
// with minimum valid length
// substring possible.
int low = 1;
// Initilise source variable high
// with maximum valid length
// substring possible.
int high = source.size();
// Do while low is less
// than equal to high
while (low <= high) {
// Calculate the mid
int mid = (low + high) / 2;
// Check if mid is possible
// length for valid substring
if (isValid(mid, source, target, conversionCost,
maxCost)) {
// Shift low to mid + 1
low = mid + 1;
}
// Otherwise shift high
// to mid - 1
else {
high = mid - 1;
}
}
if (startPos == -1)
cout << "Not possible\n";
else
cout << startPos << " " << endPos << "\n";
} // Driver code int main()
{ // First test case
string source = "adcf", target = "cdef";
int conversionCost = 3, maxCost = 5;
// Function Call
validSubstring(source, target, conversionCost, maxCost);
return 0;
} |
// Java code for the above approach class GFG {
// Initilise source variable startPos
// and endPos for storing the starting
// and ending position of valid
// substring respectively.
static int startPos = - 1 , endPos = - 1 ;
// Function to check if a substring
// of a given length is a
// valid substring.
static boolean isValid( int len, String s, String t,
int conversionCost, int maxCost)
{
int start = 0 , end = 0 , n = s.length();
int currCost = 0 ;
while (end < n) {
// Increment the current
// cost if characters are
// different.
if (s.charAt(end) != t.charAt(end)) {
currCost += conversionCost;
}
// If the substring length matches
// the given length.
if (end - start + 1 == len) {
// Check if the cost is within
// the maximum cost.
if (currCost <= maxCost) {
// Update the starting position
// of the valid substring.
startPos = start;
// Update the ending position
// of the valid substring.
endPos = end;
// Return true as this is a
// valid substring.
return true ;
}
// Subtract the cost
// if the first
// character of the
// previous substring
// was different.
if (s.charAt(start) != t.charAt(start)) {
currCost -= conversionCost;
}
// Move the start of the substring.
start++;
// Move the end of the substring.
end++;
}
// Increment the end position of the
// substring.
else {
end++;
}
}
// If no valid substring is found,
// return false.
return false ;
}
static void validSubstring(String source, String target,
int conversionCost,
int maxCost)
{
// Initilise source variable low
// with minimum valid length
// substring possible.
int low = 1 ;
// Initilise source variable high
// with maximum valid length
// substring possible.
int high = source.length();
// Do while low is less
// than equal to high
while (low <= high) {
// Calculate the mid
int mid = (low + high) / 2 ;
// Check if mid is possible
// length for valid substring
if (isValid(mid, source, target, conversionCost,
maxCost)) {
// Shift low to mid + 1
low = mid + 1 ;
}
// Otherwise shift high
// to mid - 1
else {
high = mid - 1 ;
}
}
if (startPos == - 1 )
System.out.println( "Not possible\n" );
else
System.out.println(startPos + " " + endPos
+ "\n" );
}
// Driver code
public static void main(String[] args)
{
// First test case
String source = "adcf" , target = "cdef" ;
int conversionCost = 3 , maxCost = 5 ;
// Function Call
validSubstring(source, target, conversionCost,
maxCost);
}
} // This code is contributed by ragul21 |
def is_valid(length, s, t, conversion_cost, max_cost):
global start_pos, end_pos
start, end, n = 0 , 0 , len (s)
curr_cost = 0
while end < n:
# Increment the current cost if characters are different.
if s[end] ! = t[end]:
curr_cost + = conversion_cost
if end - start + 1 = = length:
# Check if the cost is within the maximum cost.
if curr_cost < = max_cost:
# Update the starting position of the valid substring.
start_pos = start
# Update the ending position of the valid substring.
end_pos = end
# Return true as this is a valid substring.
return True
# Subtract the cost if the first character
# of the previous substring was different.
if s[start] ! = t[start]:
curr_cost - = conversion_cost
# Move the start of the substring.
start + = 1
# Move the end of the substring.
end + = 1
else :
# Increment the end position of the substring.
end + = 1
# If no valid substring is found, return false.
return False
def valid_substring(source, target, conversion_cost, max_cost):
global start_pos, end_pos
# Initialize source variable low with the
# minimum valid length substring possible.
low = 1
# Initialize source variable high with the
# maximum valid length substring possible.
high = len (source)
# Do while low is less than equal to high
while low < = high:
# Calculate the mid
mid = (low + high) / / 2
# Check if mid is a possible length for a valid substring
if is_valid(mid, source, target, conversion_cost, max_cost):
# Shift low to mid + 1
low = mid + 1
else :
# Otherwise shift high to mid - 1
high = mid - 1
if start_pos = = - 1 :
print ( "Not possible" )
else :
print (f "{start_pos} {end_pos}" )
# Driver code source_str = "adcf"
target_str = "cdef"
# Function Call conversion_cost_val = 3
max_cost_val = 5
start_pos, end_pos = - 1 , - 1
valid_substring(source_str, target_str, conversion_cost_val, max_cost_val) |
// C# code for the above approach using System;
class GFG
{ // Initialize source variable startPos
// and endPos for storing the starting
// and ending position of valid
// substring respectively.
static int startPos = -1, endPos = -1;
// Function to check if a substring
// of a given length is a
// valid substring.
static bool IsValid( int len, string s, string t,
int conversionCost, int maxCost)
{
int start = 0, end = 0, n = s.Length;
int currCost = 0;
while (end < n)
{
// Increment the current
// cost if characters are
// different.
if (s[end] != t[end])
{
currCost += conversionCost;
}
// If the substring length matches
// the given length.
if (end - start + 1 == len)
{
// Check if the cost is within
// the maximum cost.
if (currCost <= maxCost)
{
// Update the starting position
// of the valid substring.
startPos = start;
// Update the ending position
// of the valid substring.
endPos = end;
// Return true as this is a
// valid substring.
return true ;
}
// Subtract the cost
// if the first
// character of the
// previous substring
// was different.
if (s[start] != t[start])
{
currCost -= conversionCost;
}
// Move the start of the substring.
start++;
// Move the end of the substring.
end++;
}
// Increment the end position of the
// substring.
else
{
end++;
}
}
// If no valid substring is found,
// return false.
return false ;
}
static void ValidSubstring( string source, string target,
int conversionCost,
int maxCost)
{
// Initialize source variable low
// with minimum valid length
// substring possible.
int low = 1;
// Initialize source variable high
// with maximum valid length
// substring possible.
int high = source.Length;
// Do while low is less
// than equal to high
while (low <= high)
{
// Calculate the mid
int mid = (low + high) / 2;
// Check if mid is possible
// length for valid substring
if (IsValid(mid, source, target, conversionCost,
maxCost))
{
// Shift low to mid + 1
low = mid + 1;
}
// Otherwise shift high
// to mid - 1
else
{
high = mid - 1;
}
}
if (startPos == -1)
Console.WriteLine( "Not possible\n" );
else
Console.WriteLine(startPos + " " + endPos
+ "\n" );
}
// Driver code
public static void Main( string [] args)
{
// First test case
string source = "adcf" , target = "cdef" ;
int conversionCost = 3, maxCost = 5;
// Function Call
ValidSubstring(source, target, conversionCost,
maxCost);
}
} // This code is contributed by uttamdp_10 |
//Javascript code for the above approach // Initilise source variable startPos // and endPos for storing the starting // and ending position of valid // substring respectively. let startPos = -1, endPos = -1; // Function to check if a substring // of a given length is a // valid substring. function isValid(len, s, t, conversionCost, maxCost) {
let start = 0, end = 0, n = s.length;
let currCost = 0;
while (end < n) {
// Increment the current
// cost if characters are
// different.
if (s[end] !== t[end]) {
currCost += conversionCost;
}
// If the substring length matches
// the given length.
if (end - start + 1 === len) {
// Check if the cost is within
// the maximum cost.
if (currCost <= maxCost) {
// Update the starting position
// of the valid substring.
startPos = start;
// Update the ending position
// of the valid substring.
endPos = end;
// Return true as this is a
// valid substring.
return true ;
}
// Subtract the cost
// if the first
// character of the
// previous substring
// was different.
if (s[start] !== t[start]) {
currCost -= conversionCost;
}
// Move the start of the substring.
start++;
// Move the end of the substring.
end++;
}
// Increment the end position of the
// substring.
else {
end++;
}
}
// If no valid substring is found,
// return false.
return false ;
} function validSubstring(source, target, conversionCost, maxCost) {
// Initilise source variable low
// with minimum valid length
// substring possible.
let low = 1;
// Initilise source variable high
// with maximum valid length
// substring possible.
let high = source.length;
// Do while low is less
// than equal to high
while (low <= high) {
// Calculate the mid
let mid = Math.floor((low + high) / 2);
// Check if mid is possible
// length for valid substring
if (isValid(mid, source, target, conversionCost, maxCost)) {
// Shift low to mid + 1
low = mid + 1;
} else {
// Otherwise shift high
// to mid - 1
high = mid - 1;
}
}
if (startPos === -1)
console.log( "Not possible" );
else
console.log(startPos + " " + endPos);
} // Driver code // First test case let source = "adcf" , target = "cdef" ;
// Function Call let conversionCost = 3, maxCost = 5; validSubstring(source, target, conversionCost, maxCost); |
1 3
Time Complexity: O(N* log(N))
Auxiliary Space: O(1)