
Data Structure
Networking
RDBMS
Operating System
Java
MS Excel
iOS
HTML
CSS
Android
Python
C Programming
C++
C#
MongoDB
MySQL
Javascript
PHP
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
- Who is Who
Minimum Cost to Delete Characters from String A to Remove Subsequence as String B
We are given two strings string A and string B along with an array that represents the cost to delete the ith character of the given string A. We need to delete some characters of string A (possibly zero or none) with the minimum cost such that no subsequence of A represents string B. We are going to see three approaches to implementing the code that is the recursive approach; the recursive and memoization approach; and tabulation or iterative dp.
Example
Let's have a look at the following example ?
Input
string a = "xanxd" string b = "xd" int cost[] = {1, 2, 3, 4, 5}
Output
5
Explanation
Here we are required to remove all the occurrences of the 'xd' from the string A as the subsequence and to do so we have two methods either we can remove 'd' from the given string and this will lead to cost 5 or we have to remove both 'x' that will again cost 1 + 4 that is 5.
Recursive Approach
In this approach, we are going to create a recursive function, which will take a current index of both strings and both strings as the parameter along with the number of indexes of the second string removed. There will be two different cases and both of them are handled separately.
If both the characters of the current string are same at any position, then we have to make decision either to remove the current character of string A with given cost otherwise we can skip this one and will not make any change in the removed variable.
If both characters are not same then we don't need to remove, then and will directly move to the next character of the string A.
Example
#include <bits/stdc++.h> using namespace std; // recursive function to get the required result int rec(string& a, string& b, int idx1, int idx2, vector<int>& cost, int rem){ // base condition to check the edge cases if(idx1 == 0 or idx2 == 0) { return rem == 0 ? 1e5:0; } if(a[idx1 - 1] == b[idx2 - 1]){ return min(cost[idx1-1] + rec(a,b, idx1-1, idx2, cost, rem), rec(a, b, idx1-1, idx2-1, cost, rem-1)); } else { return rec(a, b, idx1-1, idx2, cost, rem); } } // function to get call to the recursive function int getCost(string a, string b, vector<int> cost){ // calling to the recursive function return rec(a, b, a.length(), b.length(), cost, b.length()); } int main(){ string a = "abccdabccdabccd"; // given string a string b = "bccd"; // given string b vector<int> cost = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; // given cost array // calling to the function to get the result cout << "Minimum cost to delete characters from String A to remove any subsequence as String B is: " << getCost(a, b, cost); return 0; }
Output
Minimum cost to delete characters from String A to remove any subsequence as String B is: 21
Time and Space Complexity
The time complexity of the above code is O(2^M) where M is the size of the given second string.
The space complexity of the above code is O(M) because we are making the recursive calls and the recursive stack stakes the memory.
Recursion + Memoization Approach
In this approach, we are going to store the results of the states that are already visited in the function call and will return that value for again calling that function leads to reduce time complexity from exponential to quadratic. Let us see the code for better understanding ?
Example
#include <bits/stdc++.h> using namespace std; int memo[105][105][3]; // array to store results // recursive function to get the required result int rec(string& a, string& b, int idx1, int idx2, vector<int>& cost, int rem){ // base condition to check the edge cases if(idx1 == 0 or idx2 == 0) { return rem == 0 ? 1e5:0; } int state = rem > 0 ? 1 : 0; if(memo[idx1][idx2][state] != -1){ return memo[idx1][idx2][state]; } if(a[idx1 - 1] == b[idx2 - 1]){ memo[idx1][idx2][state] = min(cost[idx1-1] + rec(a,b, idx1-1, idx2, cost, rem), rec(a, b, idx1-1, idx2-1, cost, rem-1)); return memo[idx1][idx2][state]; } else { memo[idx1][idx2][state] = rec(a, b, idx1-1, idx2, cost, rem); return memo[idx1][idx2][state]; } } // function to get call to the recursive function int getCost(string a, string b, vector<int> cost){ memset(memo, -1, sizeof(memo)); // calling to the recursive function return rec(a, b, a.length(), b.length(), cost, b.length()); } int main(){ string a = "abccdabccdabccd"; // given string a string b = "bccd"; // given string b vector<int> cost = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; // given cost array // calling to the function to get the result cout << "Minimum cost to delete characters from String A to remove any subsequence as String B is:" << getCost(a, b, cost); return 0; }
Output
Minimum cost to delete characters from String A to remove any subsequence as String B is: 21
Time and Space Complexity
The time complexity of the above code is O(N*M) where M is the size of the given second string and N is of the first string.
The space complexity of the above code is O(N*M) because we are using a 3-D array (which is approx of N*M size).
Conclusion
In this tutorial, we have implemented a problem to find the minimum cost to delete characters from given string A to remove any subsequence as of given string B. Where the cost of each character of string A is also given to us. First, we implemented a recursive approach then we updated it to a memoization approach where we stored the result of visited states and stored in an array to reduce time complexity.