Related Articles

Related Articles

Maximize count of non overlapping substrings which contains all occurrences of its characters
  • Last Updated : 09 Dec, 2020

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 minimum total length.

Examples:

Input: str = “abbaccd” 
Output: bb cc d 
Explanation: 
Maximum number of substrings such that all occurrences of its characters in the string are present the substring 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 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 variable i and check if i is the leftmost index of str[i], check if te substring starting from the ith positon consisting of all occurrences of str[i] does not overlap with any of the substrings consisting of characters upto 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++

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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<<" ";
    }
}
    

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 program to implement
# the above approach
 
# Function to check if subcontains
# 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 sub 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

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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

chevron_right


Output: 

bb cc d

 

Time Complexity: O(N * 26) 
Auxiliary Space: O(26)

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.




My Personal Notes arrow_drop_up
Recommended Articles
Page :