Maximize count of non overlapping substrings which contains all occurrences of its characters
Given string str consisting of lowercase letters, the task is to find the maximum number of non-overlapping substrings such that each substring contains all occurrences of its characters from the entire string. If multiple solutions with the same number of substrings exist, then print the one with the minimum total length.
Examples:
Input: str = “abbaccd”
Output: bb cc d
Explanation:
The maximum number of substrings is such that all occurrences of its characters in the string are present.The substrings are {{d, bb, cc}, {d, abba, cc}}
Therefore, the substrings of smallest possible length are {d, bb, cc}.
Input: str = “adefaddaccc”
Output: e f ccc
Approach: The problem can be solved using the Greedy technique. Follow the steps below to solve the problem:
- Initialize an array, say res[], to store the required substrings.
- Initialize two arrays, say L[] and R[], to store the leftmost and rightmost indices of all possible characters of the given string respectively.
- Traverse the string and store the leftmost and rightmost index of all possible characters of the given string.
- Traverse the string using the variable i and check if i is the leftmost index of str[i], check if the substring starting from the ith position consisting of all occurrences of str[i] does not overlap with any of the substrings consisting of characters up to str[i -1] or not. If found to be true, then append the current substring into res[].
- Finally, print the res[] array.
Below is the implementation of the above approach:
C++
// C++ program to implement // the above approach #include <bits/stdc++.h> using namespace std; // Function to check if substring contains all // occurrences of each character of str or not int checkValid(string str, int i, int L[], int R[]){ // Stores rightmost index of str[i] int right = R[str[i] - 'a' ]; // Traverse the current substring for ( int j = i; j < right; j++){ // If leftmost index of str[j] // less than i if (L[str[j] - 'a' ] < i) return -1; // Update right right = max(right, R[str[j] - 'a' ]); } return right; } // Function to find maximum number of substring // that satisfy the condition vector<string> maxcntOfSubstrings(string str) { // Stores all substrings that // satisfy the condition vector<string> res; // Stores length of str int n = str.length(); // Stores leftmost index // of each character int L[26]; // Stores rightmost index // of each character int R[26]; // Initialize L[] and R[] for ( int i = 0; i <26; i++) { // Initialize L[i] // and R[i] L[i] = R[i] = -1; } // Traverse the string for ( int i = 0; i < n; i++) { // If str[i] not // already occurred if (L[str[i] - 'a' ] == -1) { // Update leftmost index // of str[i] L[str[i] - 'a' ] = i; } // Update rightmost index // of str[i] R[str[i]- 'a' ] = i; } // Stores rightmost index of last // substring inserted into res[] int right = -1; // Traverse the string for ( int i = 0; i < n; i++) { // If i is leftmost index of str[i] if (i == L[str[i] - 'a' ]) { // Check if a new substring starting // from i satisfies the conditions or not int new_right = checkValid(str, i, L, R); // If the substring starting from i // satisfies the conditions if (new_right != -1){ // Stores the substring starting from // i that satisfy the condition string sub = str.substr(i, new_right - i + 1); // If the substring overlaps // with another substring if (new_right < right){ // Stores sub to the last // of res res.back() = sub; } else { // If sub not overlaps to // other string then append // sub to the end of res res.push_back(sub); } // Update right right = new_right; } } } return res; } // Driver Code int main() { string str = "abbaccd" ; // Stores maximum number of substring // that satisfy the condition vector<string> res = maxcntOfSubstrings(str); // Print all substring for ( auto sub : res) { cout<<sub<< " " ; } } |
Java
// Java program to implement // the above approach import java.util.*; class GFG{ // Function to check if subString contains all // occurrences of each character of str or not static int checkValid(String str, int i, int L[], int R[]) { // Stores rightmost index of str.charAt(i) int right = R[( int )(str.charAt(i)) - 97 ]; // Traverse the current subString for ( int j = i; j < right; j++) { // If leftmost index of str[j] // less than i if (L[( int )(str.charAt(j)) - 97 ] < i) return - 1 ; // Update right right = Math.max(right, R[( int )(str.charAt(j)) - 97 ]); } return right; } // Function to find maximum number of subString // that satisfy the condition static Vector<String> maxcntOfSubStrings(String str) { // Stores all subStrings that // satisfy the condition Vector<String> res = new Vector<String>(); // Stores length of str int n = str.length(); // Stores leftmost index // of each character int []L = new int [ 26 ]; // Stores rightmost index // of each character int []R = new int [ 26 ]; // Initialize L[] and R[] for ( int i = 0 ; i < 26 ; i++) { // Initialize L[i] // and R[i] L[i] = R[i] = - 1 ; } // Traverse the String for ( int i = 0 ; i < n; i++) { // If str.charAt(i) not // already occurred if (L[( int )(str.charAt(i)) - 97 ] == - 1 ) { // Update leftmost index // of str.charAt(i) L[( int )(str.charAt(i)) - 97 ] = i; } // Update rightmost index // of str.charAt(i) R[( int )(str.charAt(i)) - 97 ] = i; } // Stores rightmost index of last // subString inserted into res[] int right = - 1 ; // Traverse the String for ( int i = 0 ; i < n; i++) { // If i is leftmost index of str.charAt(i) if (i == L[( int )(str.charAt(i)) - 97 ]) { // Check if a new subString starting // from i satisfies the conditions or not int new_right = checkValid(str, i, L, R); // If the subString starting from i // satisfies the conditions if (new_right != - 1 ) { // Stores the subString starting from // i that satisfy the condition String sub = str.substring(i, new_right + 1 ); // If the subString overlaps // with another subString if (new_right < right) { // Stores sub to the last // of res res.set(res.size() - 1 , sub); } else { // If sub not overlaps to // other String then append // sub to the end of res res.add(sub); } // Update right right = new_right; } } } return res; } // Driver Code public static void main(String args[]) { String str = "abbaccd" ; // Stores maximum number of subString // that satisfy the condition Vector<String> res = maxcntOfSubStrings(str); // Print all subString for ( int i = 0 ; i < res.size(); i++) { System.out.print(res.get(i) + " " ); } } } // This code is contributed by SURENDRA_GANGWAR |
Python3
# Python3 program to implement # the above approach # Function to check if substring contains # all occurrences of each character # of str or not def checkValid( str ,i, L, R): # Stores rightmost index # of str[i] right = R[ ord ( str [i]) - ord ( 'a' )] # Traverse the current sub for j in range (i, right): # If leftmost index of str[j] # less than i if (L[ ord ( str [j]) - ord ( 'a' )] < i): return - 1 # Update right right = max (right, R[ ord ( str [j]) - ord ( 'a' )]) return right # Function to find maximum # number of substring that satisfy # the condition def maxcntOfSubstrings( str ): # Stores all substrings that # satisfy the condition res = [] # Stores length of str n = len ( str ) # Stores leftmost index # of each character L = [ - 1 ] * 26 # Stores rightmost index # of each character R = [ - 1 ] * 26 for j, i in enumerate ( str ): x = ord (i) - ord ( 'a' ) # If str[i] not # already occurred if L[x] = = - 1 : # Update leftmost index # of str[i] L[x] = j # Update rightmost index # of str[i] R[x] = j # Stores rightmost index of # last substring inserted # into res[] right = - 1 for j, i in enumerate ( str ): x = ord (i) - ord ( 'a' ) # If i is leftmost index # of str[i] if j = = L[x]: # Check if a new substring # starting from i satisfies # the conditions or not new_right = checkValid( str , j, L, R) # If the substring starting # from i satisfies the conditions if new_right ! = - 1 : # Stores the substring starting # from i that satisfy the condition sub = str [j : new_right + 1 ] # If the substring overlaps # with another substring if new_right < right: res[ - 1 ] = sub else : # If sub not overlaps to # other string then append # sub to the end of res res.append(sub) right = new_right return res # Driver Code if __name__ = = '__main__' : str = "abbaccd" # Stores maximum number of sub # that satisfy the condition res = maxcntOfSubstrings( str ) # Print sub for sub in res: print (sub, end = " " ) # This code is contributed by Mohit Kumar 29 |
C#
// C# program to implement // the above approach using System; using System.Collections.Generic; class GFG { // Function to check if substring contains all // occurrences of each character of str or not static int checkValid( string str, int i, int [] L, int [] R) { // Stores rightmost index of str[i] int right = R[str[i] - 'a' ]; // Traverse the current substring for ( int j = i; j < right; j++){ // If leftmost index of str[j] // less than i if (L[str[j] - 'a' ] < i) return -1; // Update right right = Math.Max(right, R[str[j] - 'a' ]); } return right; } // Function to find maximum number of substring // that satisfy the condition static List< string > maxcntOfSubstrings( string str) { // Stores all substrings that // satisfy the condition List< string > res = new List< string >(); // Stores length of str int n = str.Length; // Stores leftmost index // of each character int [] L = new int [26]; // Stores rightmost index // of each character int [] R = new int [26]; // Initialize L[] and R[] for ( int i = 0; i <26; i++) { // Initialize L[i] // and R[i] L[i] = R[i] = -1; } // Traverse the string for ( int i = 0; i < n; i++) { // If str[i] not // already occurred if (L[str[i] - 'a' ] == -1) { // Update leftmost index // of str[i] L[str[i] - 'a' ] = i; } // Update rightmost index // of str[i] R[str[i]- 'a' ] = i; } // Stores rightmost index of last // substring inserted into res[] int right = -1; // Traverse the string for ( int i = 0; i < n; i++) { // If i is leftmost index of str[i] if (i == L[str[i] - 'a' ]) { // Check if a new substring starting // from i satisfies the conditions or not int new_right = checkValid(str, i, L, R); // If the substring starting from i // satisfies the conditions if (new_right != -1){ // Stores the substring starting from // i that satisfy the condition string sub = str.Substring(i, new_right - i + 1); // If the substring overlaps // with another substring if (new_right < right){ // Stores sub to the last // of res res[res.Count - 1] = sub; } else { // If sub not overlaps to // other string then append // sub to the end of res res.Add(sub); } // Update right right = new_right; } } } return res; } // Driver code static void Main() { string str = "abbaccd" ; // Stores maximum number of substring // that satisfy the condition List< string > res = maxcntOfSubstrings(str); // Print all substring foreach ( string sub in res) { Console.Write(sub + " " ); } } } // This code is contributed by divyeshrabadiya |
Javascript
<script> // JavaScript program to implement // the above approach // Function to check if substring contains all // occurrences of each character of str or not function checkValid(str, i, L, R) { // Stores rightmost index of str[i] var right = R[str[i].charCodeAt(0) - "a" .charCodeAt(0)]; // Traverse the current substring for ( var j = i; j < right; j++) { // If leftmost index of str[j] // less than i if (L[str[j].charCodeAt(0) - "a" .charCodeAt(0)] < i) return -1; // Update right right = Math.max(right, R[str[j].charCodeAt(0) - "a" .charCodeAt(0)]); } return right; } // Function to find maximum number of substring // that satisfy the condition function maxcntOfSubstrings(str) { // Stores all substrings that // satisfy the condition var res = []; // Stores length of str var n = str.length; // Stores leftmost index // of each character var L = new Array(26).fill(-1); // Stores rightmost index // of each character var R = new Array(26).fill(-1); // Traverse the string for ( var i = 0; i < n; i++) { var x = str[i].charCodeAt(0) - "a" .charCodeAt(0); // If str[i] not // already occurred if (L[x] === -1) { // Update leftmost index // of str[i] L[x] = i; } // Update rightmost index // of str[i] R[x] = i; } // Stores rightmost index of last // substring inserted into res[] var right = -1; // Traverse the string for ( var i = 0; i < n; i++) { var x = str[i].charCodeAt(0) - "a" .charCodeAt(0); // If i is leftmost index of str[i] if (i === L[x]) { // Check if a new substring starting // from i satisfies the conditions or not var new_right = checkValid(str, i, L, R); // If the substring starting from i // satisfies the conditions if (new_right !== -1) { // Stores the substring starting from // i that satisfy the condition var sub = str.substring(i, new_right + 1); // If the substring overlaps // with another substring if (new_right < right) { // Stores sub to the last // of res res[res.length - 1] = sub; } else { // If sub not overlaps to // other string then append // sub to the end of res res.push(sub); } // Update right right = new_right; } } } return res; } // Driver code var str = "abbaccd" ; // Stores maximum number of substring // that satisfy the condition var res = maxcntOfSubstrings(str); // Print all substring for (const sub of res) { document.write(sub + " " ); } </script> |
bb cc d
Time Complexity: O(N * 26)
Auxiliary Space: O(26)
Please Login to comment...