![Trending Articles on Technical and Non Technical topics](/images/trending_categories.jpeg)
Data Structure
Networking
RDBMS
Operating System
Java
MS Excel
iOS
HTML
CSS
Android
Python
C Programming
C++
C#
MongoDB
MySQL
Javascript
PHP
Physics
Chemistry
Biology
Mathematics
English
Economics
Psychology
Social Studies
Fashion Studies
Legal Studies
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
- Who is Who
Longest Substring of A that can be changed to Substring of B in at most T cost
In this problem, we will find the longest substring of A to convert it to a substring of B starting from the same index in less than T cost.
We will use the binary search algorithm to find the maximum length of the substring which follows the given condition. However, the naïve approach to solving the problem is to find all substrings following the conditions in the problem statement and take the substring with maximum length.
Problem statement − We have given a string A and B of length N. Also, we have given a total cost, ‘T’. The K is the cost of converting one character to another.
We need to find the longest substring of the A string such that we can make it the same as a substring starting from the same index in the B string, and the total cost of converting one substring to another should not exceed the T. Also, print the starting and ending index of such substrings.
Sample Examples
Input
A = "wxyz", B = "wpqt"; K = 2, T = 5;
Output
Starting index – 0, ending index - 2
Explanation
We can convert the ‘wxy’ to ‘wpq’ with cost 4, which is less than 5.
Input
A = "wxyz", B = "ewrt"; K = 6, T = 5;
Output
‘Not possible.’
Explanation
Here, K is greater than T, and no substrings are the same, starting at the same index. So, it is not possible to find the substrings.
Input
A = "pqdetr", B = "tqcets"; K = 1, T = 5;
Output
Starting index – 0, ending index - 5
Explanation
We can take string A as a substring as its 5 characters is different, which we can make the same as string B with cost 5.
Approach 1
We will use the binary search algorithm to solve the problem in this approach. We will check whether a valid substring exists of the ‘mid-length. If yes, we will find the valid substring length in the range [mid, string_length]. Otherwise, we will find the valid string length in the [0, mid].
We will use the sliding window technique to find the valid substring of the particular length.
Algorithm
Step 1 − Initialize the st_ind and end_ind variables with -1 to store the starting and ending indexes of the maximum length substring.
Step 2 − Initialize the ‘left’ pointer with 0 and ‘right’ with the string length + 1. Also, initialize the ‘maxLen’ with 0 to store the maximum length of the substring.
Step 3 − Now, we need to use the binary search technique. So, start making iterations using the while loop until the left pointer’s value is less than the right pointer’s.
Step 4 − Find the mid-length by dividing the summation of left and right with 2.
Step 5 − Execute the isMidValid() function to check whether any substring exists of length equal to the ‘mid-length.
Step 5.1 − In the isMidValid() function, initialize the ‘p’ and ‘q’ variables with 0 for the sliding window pointer. Also, initialize the ‘ct’ with 0 to store the cost of the current window to make it the same as string B’s substring.
Step 5.2 − Initialize the ‘isValid’ variable with false to track whether a valid substring exists.
Step 5.3 − Use the loop to make iterations until ‘q’ is less than string A’s length. In the loop, If A[q] and B[q] are not the same, add K, the cost to convert one character to another to the ‘ct’.
Step 5.4 − If the length of the current window is equal to ‘midLen’, follow the steps below.
Steps 5.4.1 − If ‘ct’ is less than T, set ‘isValid’ to true, update ‘st_ind’ with p, and ‘end_ind’ with q.
Step 5.4.2 − To move to the next window of ‘midLen’ length, remove the cost of ‘A[p]’ from the ‘ct’, and increment ‘p’ value by 1.
Step 5.5 − Increment ‘q’ value by 1.
Step 5.6 − Return the value of the ‘isValid’ variable.
Step 6 − If the function returns true, Update the ‘maxLen’ and search for the maximum length in the right half. Otherwise, search maximum length in the left half.
Step 7 − At last, if the value of the ‘st_ind’ is -1, substring is impossible. Otherwise, print the starting and ending index of the longest valid substring.
Example
Following are the programs to the above algorithm −
#include <stdio.h> #include <string.h> // Starting and ending position of valid substring int st_ind = -1, end_ind = -1; int isMidValid(int midLen, char A[], char B[], int K, int T) { int p = 0, q = 0, len = strlen(A), ct = 0; // To track whether any substring of length MidLen is valid int isValid = 0; while (q < len) { // Cost for converting one character to another ct += (A[q] != B[q]) ? K : 0; // Shifting the window to the right if (q - p + 1 == midLen) { // For cost less than T if (ct <= T) { isValid = 1; st_ind = p; end_ind = q; } // Removing the left character from the window ct -= (A[p] != B[p]) ? K : 0; p++; } q++; } // Output return isValid; } void printLongestSubstr(char A[], char B[], int K, int T) { st_ind = -1, end_ind = -1; // Left and right pointers for binary search int left = 0; int right = strlen(A) + 1; // To store the maximum length int maxLen = 0; while (left < right) { // Mid calculation int midLen = (left + right) / 2; // If midLen length is valid if (isMidValid(midLen, A, B, K, T)) { // Update max length maxLen = midLen; // Find the maximum length in the right half left = midLen + 1; } else { // If mid is invalid, then find in the left half right = midLen; } } if (st_ind == -1) printf("Not possible\n"); else printf("Starting index - %d ending index - %d\n", st_ind, end_ind); } int main() { char A[] = "wxyz"; char B[] = "wpqt"; int K = 2, T = 5; printLongestSubstr(A, B, K, T); return 0; }
Output
Starting index - 0 ending index - 2
#include <bits/stdc++.h> using namespace std; // Starting and ending position of valid substring int st_ind = -1, end_ind = -1; bool isMidValid(int midLen, string &A, string &B, int K, int T) { int p = 0, q = 0, len = A.size(), ct = 0; // To track whether any substring of length MidLen is valid bool isValid = false; while (q < len) { // Cost for converting one character to other ct += ((A[q] != B[q]) ? K : 0); // Shifting the window to right if (q - p + 1 == midLen) { // For cost less than T if (ct <= T) { isValid = true; st_ind = p; end_ind = q; } // Removing left character from window ct -= ((A[p] != B[p]) ? K : 0); p++; } q++; } // output return isValid; } void printLongestSubstr(string A, string B, int K, int T) { st_ind = -1, end_ind = -1; // Left and right pointers for binary search int left = 0; int right = A.size() + 1; int len = A.size(); // To store the maximum length int maxLen = 0; while (left < right) { // Mid calculation int midLen = (left + right) / 2; // If midLen length is valid if (isMidValid(midLen, A, B, K, T)) { // Update max length maxLen = midLen; // Find the maximum length in the right half left = midLen + 1; } else { // If mid is invalid, then find in the left half right = midLen; } } if (st_ind == -1) cout << "Not possible\n"; else cout << "Starting index - " << st_ind << " ending index - " << end_ind << "\n"; } int main() { string A = "wxyz", B = "wpqt"; int K = 2, T = 5; printLongestSubstr(A, B, K, T); return 0; }
Output
Starting index - 0 ending index - 2
public class LongestValidSubstring { // Starting and ending position of valid substring static int st_ind = -1; static int end_ind = -1; public static boolean isMidValid(int midLen, String A, String B, int K, int T) { int p = 0; int q = 0; int len = A.length(); int ct = 0; // To track whether any substring of length MidLen is valid boolean isValid = false; while (q < len) { // Cost for converting one character to other ct += (A.charAt(q) != B.charAt(q)) ? K : 0; // Shifting the window to the right if (q - p + 1 == midLen) { // For cost less than T if (ct <= T) { isValid = true; st_ind = p; end_ind = q; } // Removing the left character from the window ct -= (A.charAt(p) != B.charAt(p)) ? K : 0; p++; } q++; } // Output return isValid; } public static void printLongestSubstr(String A, String B, int K, int T) { st_ind = -1; end_ind = -1; // Left and right pointers for binary search int left = 0; int right = A.length() + 1; // To store the maximum length int maxLen = 0; while (left < right) { // Mid calculation int midLen = (left + right) / 2; // If midLen length is valid if (isMidValid(midLen, A, B, K, T)) { // Update max length maxLen = midLen; // Find the maximum length in the right half left = midLen + 1; } else { // If mid is invalid, then find in the left half right = midLen; } } if (st_ind == -1) { System.out.println("Not possible"); } else { System.out.println("Starting index - " + st_ind + " ending index - " + end_ind); } } public static void main(String[] args) { String A = "wxyz"; String B = "wpqt"; int K = 2; int T = 5; printLongestSubstr(A, B, K, T); } }
Output
Starting index - 0 ending index - 2
# Starting and ending position of valid substring st_ind = -1 end_ind = -1 def is_mid_valid(mid_len, A, B, K, T): global st_ind, end_ind p = 0 q = 0 len_A = len(A) ct = 0 # To track whether any substring of length MidLen is valid is_valid = False while q < len_A: # Cost for converting one character to another ct += K if A[q] != B[q] else 0 # Shifting the window to the right if q - p + 1 == mid_len: # For cost less than T if ct <= T: is_valid = True st_ind = p end_ind = q # Removing the left character from the window ct -= K if A[p] != B[p] else 0 p += 1 q += 1 # Output return is_valid def print_longest_substr(A, B, K, T): global st_ind, end_ind st_ind = -1 end_ind = -1 # Left and right pointers for binary search left = 0 right = len(A) + 1 # To store the maximum length max_len = 0 while left < right: # Mid calculation mid_len = (left + right) // 2 # If mid_len length is valid if is_mid_valid(mid_len, A, B, K, T): # Update max length max_len = mid_len # Find the maximum length in the right half left = mid_len + 1 else: # If mid is invalid, then find in the left half right = mid_len if st_ind == -1: print("Not possible") else: print(f"Starting index - {st_ind} ending index - {end_ind}") A = "wxyz" B = "wpqt" K = 2 T = 5 print_longest_substr(A, B, K, T)
Output
Starting index - 0 ending index - 2
Time complexity – O((logN)*N), where O(N) is for sliding window and O(logN) is for binary search.
Space complexity – O(1), as we don’t use any dynamic space.
Conclusion
We have used the binary search and sliding window, two different algorithms, to solve the single problem. In many cases, we need to use multiple algorithms to solve the problem.