Maximum string length after choosing strings from given Array with given conditions


In this problem, we need to find the maximum length of the resultant string by appending the array strings to it such that if we choose a string of length x, we can choose the next x/2 strings.

We can solve the programming using the recursive function, memoization, and dynamic programming approach.

Problem statement - We have given an array of strings named str_array containing the N strings. We need to add the strings given in the array and find the maximum size of the resultant string. While appending the string to the resultant string, we need to follow the rule: if we choose any string whose length is x, we can't choose the next x/2 strings from the array.

Sample examples

Input

str_array[] = {"tutor", "po", "nt", "welco", "ghj"}

Output

10

Explanation - We can choose the 'tutor' and 'welco' string.

Input

str_array[] = {"tu", "po", "nt", "wel", "ghj"}

Output

7

Explanation - We can choose the 'tu', 'nt', and 'ghj' strings. The length of the resultant string will be 7.

Input

str_array[] = {"tutorialspoint", "po", "nt", "wel", "ghj"};

Output

14

Explanation - We can choose the 'tutorialspoint' string only.

To solve the problem, we need to make a total of 2N choices of the string and select the final answer according to the choice have a maximum length.

Approach 1

In this approach, we will create a recursive function to consider all choices of the string, and based on all the choices, we will choose the maximum length.

Algorithm

Step 1 - First, define the base case. If the array length is less than start, return 0.

Step 2 - Now, we have to make a choice for the current string. The first option is to include the string. If we include the string, add string size to the returned value from the recursive function. Also, change the start parameter value as we can't choose the next x/2 length, where x is the string length.

Step 3 - If we don't include the current string, make a recursive function call after incrementing the start parameter value by 1.

Step 4 - Take the maximum from sol1 and sol2 and return it.

Example

#include <bits/stdc++.h>
using namespace std;

int maxStringSize(string str_array[], int len, int start) {
   // Return 0 if start exceeds len
   if (start >= len)
      return 0;
   // If value is not calculated for start index
       // Add current string
      int sol1 = str_array[start].size() + maxStringSize(str_array, len, 
(start + str_array
[start].size() / 2) + 1);
      // Remove current string
      int sol2 = maxStringSize(str_array, len, start + 1);
      // Take max of both
      int maxSize = max(sol1, sol2);
   // return answer
   return maxSize;
}
int main() {
   string str_array[] = {"tutor", "po", "nt", "welco", "ghj"};
   int len = sizeof(str_array) / sizeof(str_array[0]);
   cout << "The maximum size of the resultant string according to given conditions is  - " << maxStringSize(str_array, len, 0);
   return 0;
}

Output

The maximum size of the resultant string according to given conditions is - 10

Time complexity - O(2^N), as we make a choice for all strings in the recursive function.

Space complexity - O(1) as we use constant space.

Approach 2

This approach will use the memorization technique to solve the problem. It stores the previously calculated results in the list. So, if we need to calculate the same operation again, we can take its value from the list.

Algorithm

Step 1 - Define the 'dp' list of lengths equal to the array length and initialize it with -1.

Step 2 - If the start is greater than the length, return 0.

Step 3 - If dp[start[ is -1, we calculate the value for the first time.

Step 4 - Execute the recursive function calls. In one function call, include the string at the start index; in one function, don't include the string at the start index.

Step 5 - Store the maximum value from both solutions in the dp[start].

Step 6 - Return the dp[start] value.

Example

#include <bits/stdc++.h>
using namespace std;

int maxStringSize(string str_array[], int len, int start, vector<int> 
&dp) {
   // Return 0 if start exceeds len
   if (start >= len)
      return 0;
   // If value is not calculated for start index
   if (dp[start] == -1) {
      // Add current string
      int sol1 = str_array[start].size() + maxStringSize(str_array, len, 
(start + str_array[start].size() / 2) + 1, dp);
      // Remove current string
      int sol2 = maxStringSize(str_array, len, start + 1, dp);
      // Take max of both
      dp[start] = max(sol1, sol2);
   }
   // return answer
   return dp[start];
}
int main() {
   string str_array[] = {"tutor", "po", "nt", "welco", "ghj"};
   int len = sizeof(str_array) / sizeof(str_array[0]);
   vector<int> dp(len, -1);
   cout << "The maximum size of the resultant string according to given conditions is " << maxStringSize(str_array, len, 0, dp);
   return 0;
}

Output

The maximum size of the resultant string according to given conditions is 10

Time complexity - O(N*M), where N is the array length, and M is the maximum length of the string.

Space complexity - O(N) as we store the resultant value for each starting index.

Approach 3

In this approach, we will use the tabulation method of dynamic programming to solve the problem. It fills the list iteratively and decides the answer based on the previous state.

Algorithm

Step 1 - Define the 'matrix' list.

Step 2 - Initialize the last element of the matrix with 0.

Step 3 - Start traversing the array from the last index.

Step 4 - Initialize the sol1 variable with the string size. If p + str_array[p].size() / 2 + 1 is less than or equal to the array length, add value to the sol1 from (p + str_array[p].size() / 2 + 1) index of the matrix.

Step 5 - Define the 'sol2' and initialize it with matrix[p+1].

Step 6 - In the matrix[p] store the maximum value from sol1 and sol2.

Step 7 - Return matrix[0] value.

Example

#include <bits/stdc++.h>
using namespace std;

int maxStringSize(string str_array[], int len) {
   // List to store results
   vector<int> matrix(len + 1);
   matrix[len] = 0; // Initialization
   // Traverse the string
   for (int p = len - 1; p >= 0; p--) {
      // Include string at pth index
      int sol1 = str_array[p].size();
      if (p + str_array[p].size() / 2 + 1 <= len) {
         sol1 += matrix[p + str_array[p].size() / 2 + 1];
      }
      // Don't include string at pth index
      int sol2 = matrix[p + 1];
      // Answer for last p strings
      matrix[p] = max(sol1, sol2);
   }
   // Return final result
   return matrix[0];
}
int main() {
   string str_array[] = {"tutor", "po", "nt", "welco", "ghj"};
   int len = sizeof(str_array) / sizeof(str_array[0]);
   cout << "The maximum size of the resultant string according to given conditions is " << maxStringSize(str_array, len);
   return 0;
}

Output

The maximum size of the resultant string according to given conditions is 10

Time complexity - O(N) as we traverse the string.

Space complexity - O(N) as we use the list to store previous results.

From the above three approaches, the tabulation technique is best regarding the time complexity. The memoization technique is the optimized version of the recursive approach as we use the previously calculated results.

Updated on: 24-Aug-2023

54 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements