Open In App

Maximize count of non overlapping substrings which contains all occurrences of its characters

Last Updated : 10 Mar, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

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>


Output: 

bb cc d

 

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



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads