Open In App

Longest Substring of A that can be changed to Substring of B in at most T cost

Last Updated : 06 Jul, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given two strings A and B of the same length and two positive integers K and T. The task is to find the longest substring of A that can be converted to the same substring at the same position in B in less than or equal to T cost. Converting any character of A to any other character costs K units.

Note: If multiple valid substrings are possible then find any one of them.

Examples: 

Input: A = “abcd”, B = “bcdf”, K = 1, T = 3
Output: 1 3
Explanation: The substring of A from index 1 to 3 is “bcd” that can change to “cdf”. The cost of changing would be 3. So the maximum length is 3.

Input: A = “adcd”, B = “cdef”, K = 2, T = 5
Output: 1 3

An approach using Binary Search:

Use binary search to determine what can be the maximum possible length, and for each length, check its possibility and decide the further range of length based on the possibility. Keep track of indices of start and end position of valid substring.

Follow the steps below to implement the above idea:

  • Initialize a variable start with the minimum valid length substring possible i.e., 0.
  • Initialize a variable end with the maximum valid length substring possible i.e., the size of the string itself.
  • Initialize a variable result for storing the maximum length of valid substring
  • While the start is less than the end, do the following:
    • Calculate the mid
    • Check if mid is the possible length for a valid substring 
      • Assign the result to mid
      • Shift start to mid + 1.
    • Otherwise, shift end to mid.
  • If any valid substring is possible then print the starting index and the ending index of the valid substring.

Below is the implementation of the above approach.

C++




#include <bits/stdc++.h>
using namespace std;
 
// Initialise a variable startPos and endPos
// for storing the starting and ending
// position of valid substring
// respectively.
int startPos = -1, endPos = -1;
 
bool isValid(int len, string& A, string& B, int K, int T)
{
    int i = 0, j = 0, n = A.size(), cost = 0;
 
    // Initialise a variable flag to false.
    // It will keep track of any valid
    // substring of length len is
    // possible or not
    bool flag = false;
 
    while (j < n) {
 
        // Include the cost required to
        // convert A[j] to B[j]
        cost += ((A[j] != B[j]) ? K : 0);
 
        // If window size is equal to len
        // then shift the window.
        if (j - i + 1 == len) {
 
            // Check if any valid substring
            // then keep the indices of
            // valid substring in startPos
            // and endPos
            if (cost <= T) {
                flag = true;
                startPos = i;
                endPos = j;
            }
 
            // Remove the calculation of
            // ith indices as our window
            // we have to slide our window
            cost -= ((A[i] != B[i]) ? K : 0);
            i++;
        }
 
        j++;
    }
 
    // Return the flag
    return flag;
}
 
void validSubstring(string A, string B, int K, int T)
{
    startPos = -1, endPos = -1;
 
    // Initialise a variable start with
    // minimum valid length
    // substring possible.
    int start = 0;
 
    // Initialise a variable end with
    // maximum valid length substring
    // possible.
    int end = A.size();
    int n = A.size();
 
    // Initialise a variable result for
    // storing the maximum length of
    // valid substring
    int result = 0;
 
    // Do while start is less
    // than equal to end
    while (start < end) {
 
        // Calculate the mid
        int mid = (start + end) / 2;
 
        // Check if mid is possible length
        // for valid substring
        if (isValid(mid, A, B, K, T)) {
 
            // Assign result to mid
            result = mid;
 
            // Shift start to mid + 1
            start = mid + 1;
        }
 
        // Otherwise shift end to mid - 1
        else {
            end = mid;
        }
    }
 
    if (startPos == -1)
        cout << "Not possible\n";
    else
        cout << startPos << " " << endPos << "\n";
}
 
// Driver code
int main()
{
    // First test case
    string A = "adcd", B = "cdef";
    int K = 2, T = 5;
    validSubstring(A, B, K, T);
 
    // Second test case
    A = "abc", B = "cdf";
    K = 4, T = 3;
    validSubstring(A, B, K, T);
 
    // Third test case
    A = "abcb", B = "cdfb";
    K = 4, T = 2;
    validSubstring(A, B, K, T);
 
    return 0;
}


Java




// Java code to implement the above approach
 
import java.io.*;
 
class GFG {
 
    // Initialise a variable startPos and endPos
    // for storing the starting and ending
    // position of valid substring
    // respectively.
    static int startPos = -1, endPos = -1;
 
    static boolean isValid(int len, String A, String B,
                           int K, int T)
    {
        int i = 0, j = 0, n = A.length(), cost = 0;
 
        // Initialise a variable flag to false.
        // It will keep track of any valid
        // substring of length len is
        // possible or not
        boolean flag = false;
 
        while (j < n) {
 
            // Include the cost required to
            // convert A[j] to B[j]
            cost += ((A.charAt(j) != B.charAt(j)) ? K : 0);
 
            // If window size is equal to len
            // then shift the window.
            if (j - i + 1 == len) {
 
                // Check if any valid substring
                // then keep the indices of
                // valid substring in startPos
                // and endPos
                if (cost <= T) {
                    flag = true;
                    startPos = i;
                    endPos = j;
                }
 
                // Remove the calculation of
                // ith indices as our window
                // we have to slide our window
                cost -= ((A.charAt(i) != B.charAt(i)) ? K
                                                      : 0);
                i++;
            }
 
            j++;
        }
 
        // Return the flag
        return flag;
    }
 
    static void validSubstring(String A, String B, int K,
                               int T)
    {
        startPos = -1;
        endPos = -1;
 
        // Initialise a variable start with
        // minimum valid length
        // substring possible.
        int start = 0;
 
        // Initialise a variable end with
        // maximum valid length substring
        // possible.
        int end = A.length();
        int n = A.length();
 
        // Initialise a variable result for
        // storing the maximum length of
        // valid substring
        int result = 0;
 
        // Do while start is less
        // than equal to end
        while (start < end) {
            // Calculate the mid
            int mid = (start + end) / 2;
 
            // Check if mid is possible length
            // for valid substring
            if (isValid(mid, A, B, K, T)) {
 
                // Assign result to mid
                result = mid;
 
                // Shift start to mid + 1
                start = mid + 1;
            }
 
            // Otherwise shift end to mid - 1
            else {
                end = mid;
            }
        }
 
        if (startPos == -1)
            System.out.println("Not possible");
        else
            System.out.println(startPos + " " + endPos);
    }
 
    public static void main(String[] args)
    {
        // First test case
        String A = "adcd", B = "cdef";
        int K = 2, T = 5;
        validSubstring(A, B, K, T);
 
        // Second test case
        A = "abc";
        B = "cdf";
        K = 4;
        T = 3;
        validSubstring(A, B, K, T);
 
        // Third test case
        A = "abcb";
        B = "cdfb";
        K = 4;
        T = 2;
        validSubstring(A, B, K, T);
    }
}
 
// This code is contributed by lokesh.


Python3




# Python3 Code for the above approach
 
# Initialise a variable startPos and endPos
# for storing the starting and ending
# position of valid substring
# respectively.
startPos = -1;
endPos = -1;
 
def isValid(length, A, B, K, T) :
    global startPos,endPos
     
    i = 0;
    j = 0;
    n = len(A);
    cost = 0;
 
    # Initialise a variable flag to false.
    # It will keep track of any valid
    # substring of length len is
    # possible or not
    flag = False;
 
    while (j < n) :
 
        # Include the cost required to
        # convert A[j] to B[j]
        if A[j] != B[j] :
            cost += K
        else :
            cost += 0
 
        # If window size is equal to len
        # then shift the window.
        if (j - i + 1 == length) :
 
            # Check if any valid substring
            # then keep the indices of
            # valid substring in startPos
            # and endPos
            if (cost <= T) :
                flag = True;
                startPos = i;
                endPos = j;
 
            # Remove the calculation of
            # ith indices as our window
            # we have to slide our window
            if A[i] != B[i] :
                cost -= K;
            else :
                cost -= 0;
                 
            i += 1;
         
 
        j += 1;
     
    # Return the flag
    return flag;
     
def validSubstring(A, B, K, T) :
    global startPos,endPos
 
    startPos = -1;
    endPos = -1;
 
    # Initialise a variable start with
    # minimum valid length
    # substring possible.
    start = 0;
 
    # Initialise a variable end with
    # maximum valid length substring
    # possible.
    end = len(A);
    n = len(A);
 
    # Initialise a variable result for
    # storing the maximum length of
    # valid substring
    result = 0;
 
    # Do while start is less
    # than equal to end
    while (start < end) :
 
        # Calculate the mid
        mid = (start + end) // 2;
 
        # Check if mid is possible length
        # for valid substring
        if (isValid(mid, A, B, K, T)) :
 
            # Assign result to mid
            result = mid;
 
            # Shift start to mid + 1
            start = mid + 1;
 
        # Otherwise shift end to mid - 1
        else :
            end = mid;
 
    if (startPos == -1) :
        print("Not possible");
    else :
        print(startPos," ",endPos);
 
# Driver code
if __name__ == "__main__" :
 
    # First test case
    A = "adcd";
    B = "cdef";
    K = 2;
    T = 5;
    validSubstring(A, B, K, T);
 
    # Second test case
    A = "abc"; B = "cdf";
    K = 4;
    T = 3;
    validSubstring(A, B, K, T);
 
    # Third test case
    A = "abcb"; B = "cdfb";
    K = 4;
    T = 2;
    validSubstring(A, B, K, T);
     
    # This code is contributed by AnkThon


C#




// C# code to implement the above approach
using System;
 
class GFG {
 
    // Initialise a variable startPos and endPos
    // for storing the starting and ending
    // position of valid substring
    // respectively.
    static int startPos = -1, endPos = -1;
 
    static bool isValid(int len, string A, string B,
                           int K, int T)
    {
        int i = 0, j = 0, n = A.Length, cost = 0;
 
        // Initialise a variable flag to false.
        // It will keep track of any valid
        // substring of length len is
        // possible or not
        bool flag = false;
 
        while (j < n) {
 
            // Include the cost required to
            // convert A[j] to B[j]
            cost += ((A[j] != B[j]) ? K : 0);
 
            // If window size is equal to len
            // then shift the window.
            if (j - i + 1 == len) {
 
                // Check if any valid substring
                // then keep the indices of
                // valid substring in startPos
                // and endPos
                if (cost <= T) {
                    flag = true;
                    startPos = i;
                    endPos = j;
                }
 
                // Remove the calculation of
                // ith indices as our window
                // we have to slide our window
                cost -= ((A[i] != B[i]) ? K: 0);
                i++;
            }
 
            j++;
        }
 
        // Return the flag
        return flag;
    }
 
    static void validSubstring(string A, string B, int K,
                               int T)
    {
        startPos = -1;
        endPos = -1;
 
        // Initialise a variable start with
        // minimum valid length
        // substring possible.
        int start = 0;
 
        // Initialise a variable end with
        // maximum valid length substring
        // possible.
        int end = A.Length;
        int n = A.Length;
 
        // Initialise a variable result for
        // storing the maximum length of
        // valid substring
        int result = 0;
 
        // Do while start is less
        // than equal to end
        while (start < end) {
            // Calculate the mid
            int mid = (start + end) / 2;
 
            // Check if mid is possible length
            // for valid substring
            if (isValid(mid, A, B, K, T)) {
 
                // Assign result to mid
                result = mid;
 
                // Shift start to mid + 1
                start = mid + 1;
            }
 
            // Otherwise shift end to mid - 1
            else {
                end = mid;
            }
        }
 
        if (startPos == -1)
            Console.WriteLine("Not possible");
        else
            Console.WriteLine(startPos + " " + endPos);
    }
 
    public static void Main(string[] args)
    {
        // First test case
        string A = "adcd", B = "cdef";
        int K = 2, T = 5;
        validSubstring(A, B, K, T);
 
        // Second test case
        A = "abc";
        B = "cdf";
        K = 4;
        T = 3;
        validSubstring(A, B, K, T);
 
        // Third test case
        A = "abcb";
        B = "cdfb";
        K = 4;
        T = 2;
        validSubstring(A, B, K, T);
    }
}
 
// This code is contributed by AnkThon


Javascript




// Initialise a variable startPos and endPos
// for storing the starting and ending
// position of valid substring
// respectively.
let startPos = -1, endPos = -1;
 
function isValid( len,  A,B,  K,  T)
{
    let i = 0, j = 0, n = A.length, cost = 0;
 
    // Initialise a variable flag to false.
    // It will keep track of any valid
    // substring of length len is
    // possible or not
    let flag = false;
 
    while (j < n) {
 
        // Include the cost required to
        // convert A[j] to B[j]
        cost += ((A[j] != B[j]) ? K : 0);
 
        // If window size is equal to len
        // then shift the window.
        if (j - i + 1 == len) {
 
            // Check if any valid substring
            // then keep the indices of
            // valid substring in startPos
            // and endPos
            if (cost <= T) {
                flag = true;
                startPos = i;
                endPos = j;
            }
 
            // Remove the calculation of
            // ith indices as our window
            // we have to slide our window
            cost -= ((A[i] != B[i]) ? K : 0);
            i++;
        }
 
        j++;
    }
 
    // Return the flag
    return flag;
}
 
function validSubstring( A,  B,  K,  T)
{
    startPos = -1, endPos = -1;
 
    // Initialise a variable start with
    // minimum valid length
    // substring possible.
    let start = 0;
 
    // Initialise a variable end with
    // maximum valid length substring
    // possible.
    let end = A.length;
    let n = A.length;
 
    // Initialise a variable result for
    // storing the maximum length of
    // valid substring
    let result = 0;
 
    // Do while start is less
    // than equal to end
    while (start < end) {
 
        // Calculate the mid
        let mid = (start + end) / 2;
 
        // Check if mid is possible length
        // for valid substring
        if (isValid(mid, A, B, K, T)) {
 
            // Assign result to mid
            result = mid;
 
            // Shift start to mid + 1
            start = mid + 1;
        }
 
        // Otherwise shift end to mid - 1
        else {
            end = mid;
        }
    }
 
    if (startPos == -1)
        console.log("Not possible");
    else
        console.log( startPos +" " +endPos);
}
 
// Driver code
 
    // First test case
    let A = "adcd", B = "cdef";
    let K = 2, T = 5;
    validSubstring(A, B, K, T);
 
    // Second test case
    A = "abc", B = "cdf";
    K = 4, T = 3;
    validSubstring(A, B, K, T);
 
    // Third test case
    A = "abcb", B = "cdfb";
    K = 4, T = 2;
    validSubstring(A, B, K, T);
 
// This code is contributed by garg28harsh.


Output

1 3
Not possible
3 3

Time Complexity: O(N* log(N))
Auxiliary Space: O(1)

Related Articles:



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads