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++ 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 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 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# 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 |
<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)