Open In App

Lexicographically smallest K-length substring containing maximum number of vowels

Improve
Improve
Like Article
Like
Save
Share
Report

Given string str containing only the lowercase English alphabet and an integer K, the task is to find a K length substring that contains the maximum number of vowels (i.e. ‘a’, ‘e’, ‘i’, ‘o’, ‘u’). If there are multiple such substrings, return the substring which is lexicographically smallest. 

Examples: 

Input: str = “geeksforgeeks”, K = 4 
Output: eeks 
Explanation: 
The substrings with the maximum count of vowels are “geek”, “eeks” which includes 2 vowels. But “eeks” is lexicographically smallest. 
Input: str = “ceebbaceeffo”, K = 3 
Output: ace 
Explanation: 
Lexicographically, substrings with the maximum count of vowels are “ace”. 

Naive Approach: 
To solve the problem mentioned above, we have to generate all the substrings of length K and store the lexicographically smallest of all such substrings which contain the maximum number of vowels. 
Time Complexity: O(N2)
 

Efficient Approach: 
The above-mentioned procedure can be optimized by creating a prefix sum array pref[] of vowels where the ith index contains the count of vowels from 0 to the ith index. The count of vowels for any substring str[l : r] can be given by pref[r]-pref[l-1]. Then, find the lexicographically smallest substring with the maximum count of vowels.
Below is the implementation of the above approach:

C++




// C++ program to find
// lexicographically smallest
// K-length substring containing
// maximum number of vowels
 
#include <bits/stdc++.h>
using namespace std;
 
// Function that prints the
// lexicographically smallest
// K-length substring containing
// maximum number of vowels
string maxVowelSubString(
    string str, int K)
{
    // Store the length of the string
    int N = str.length();
 
    // Initialize a prefix sum array
    int pref[N];
 
    // Loop through the string to
    // create the prefix sum array
    for (int i = 0; i < N; i++) {
 
        // Store 1 at the index
        // if it is a vowel
        if (str[i] == 'a'
            or str[i] == 'e'
            or str[i] == 'i'
            or str[i] == 'o'
            or str[i] == 'u')
            pref[i] = 1;
 
        // Otherwise, store 0
        else
            pref[i] = 0;
 
        // Process the prefix array
        if (i)
            pref[i] += pref[i - 1];
    }
 
    // Initialize the variable to store
    // maximum count of vowels
    int maxCount = pref[K - 1];
 
    // Initialize the variable
    // to store substring
    // with maximum count of vowels
    string res = str.substr(0, K);
 
    // Loop through the prefix array
    for (int i = K; i < N; i++) {
 
        // Store the current
        // count of vowels
        int currCount
            = pref[i]
              - pref[i - K];
 
        // Update the result if current count
        // is greater than maximum count
        if (currCount > maxCount) {
 
            maxCount = currCount;
            res = str.substr(i - K + 1, K);
        }
 
        // Update lexicographically smallest
        // substring if the current count
        // is equal to the maximum count
        else if (currCount == maxCount) {
 
            string temp
                = str.substr(
                    i - K + 1, K);
 
            if (temp < res)
                res = temp;
        }
    }
 
    // Return the result
    return res;
}
 
// Driver Program
int main()
{
    string str = "ceebbaceeffo";
    int K = 3;
 
    cout << maxVowelSubString(str, K);
 
    return 0;
}


Java




// Java program to find
// lexicographically smallest
// K-length substring containing
// maximum number of vowels
class GFG{
 
// Function that prints the
// lexicographically smallest
// K-length substring containing
// maximum number of vowels
static String maxVowelSubString(String str,
                                int K)
{
  // Store the length of the string
  int N = str.length();
 
  // Initialize a prefix sum array
  int []pref = new int[N];
 
  // Loop through the string to
  // create the prefix sum array
  for (int i = 0; i < N; i++)
  {
    // Store 1 at the index
    // if it is a vowel
    if (str.charAt(i) == 'a' ||
        str.charAt(i) == 'e' ||
        str.charAt(i) == 'i' ||
        str.charAt(i) == 'o' ||
        str.charAt(i) == 'u')
      pref[i] = 1;
 
    // Otherwise, store 0
    else
      pref[i] = 0;
 
    // Process the prefix array
    if (i != 0)
      pref[i] += pref[i - 1];
  }
 
  // Initialize the variable to store
  // maximum count of vowels
  int maxCount = pref[K - 1];
 
  // Initialize the variable
  // to store substring
  // with maximum count of vowels
  String res = str.substring(0, K);
 
  // Loop through the prefix array
  for (int i = K; i < N; i++)
  {
    // Store the current
    // count of vowels
    int currCount = pref[i] -
                    pref[i - K];
 
    // Update the result if current count
    // is greater than maximum count
    if (currCount > maxCount)
    {
      maxCount = currCount;
      res = str.substring(i - K + 1,
                          i + 1);
    }
 
    // Update lexicographically smallest
    // substring if the current count
    // is equal to the maximum count
    else if (currCount == maxCount)
    {
      String temp = str.substring(i - K + 1,
                                  i + 1);
 
      if (temp.compareTo(res) < 0)
        res = temp;
    }
  }
 
  // Return the result
  return res;
}
 
// Driver Code
public static void main(String []args)
{
  String str = "ceebbaceeffo";
  int K = 3;
  System.out.print(maxVowelSubString(str, K));
}
}
 
// This code is contributed by Chitranayal


Python3




# Python3 program to find
# lexicographically smallest
# K-length substring containing
# maximum number of vowels
 
# Function that prints the
# lexicographically smallest
# K-length substring containing
# maximum number of vowels
def maxVowelSubString(str1, K):
     
    # Store the length of the string
    N = len(str1)
 
    # Initialize a prefix sum array
    pref = [0 for i in range(N)]
 
    # Loop through the string to
    # create the prefix sum array
    for i in range(N):
         
        # Store 1 at the index
        # if it is a vowel
        if (str1[i] == 'a' or
            str1[i] == 'e' or
            str1[i] == 'i' or
            str1[i] == 'o' or
            str1[i] == 'u'):
            pref[i] = 1
 
        # Otherwise, store 0
        else:
            pref[i] = 0
 
        # Process the prefix array
        if (i):
            pref[i] += pref[i - 1]
 
    # Initialize the variable to
    # store maximum count of vowels
    maxCount = pref[K - 1]
 
    # Initialize the variable
    # to store substring with
    # maximum count of vowels
    res = str1[0:K]
 
    # Loop through the prefix array
    for i in range(K, N):
         
        # Store the current
        # count of vowels
        currCount = pref[i] - pref[i - K]
 
        # Update the result if current count
        # is greater than maximum count
        if (currCount > maxCount):
            maxCount = currCount
            res = str1[i - K + 1 : i + 1]
 
        # Update lexicographically smallest
        # substring if the current count
        # is equal to the maximum count
        elif (currCount == maxCount):
            temp = str1[i - K + 1 : i + 1]
 
            if (temp < res):
                res = temp
 
    # Return the result
    return res
 
# Driver code
if __name__ == '__main__':
     
    str1 = "ceebbaceeffo"
    K = 3
 
    print(maxVowelSubString(str1, K))
 
# This code is contributed by Surendra_Gangwar


C#




// C# program to find
// lexicographically smallest
// K-length substring containing
// maximum number of vowels
using System;
class GFG{
 
// Function that prints the
// lexicographically smallest
// K-length substring containing
// maximum number of vowels
static string maxVowelSubString(string str,
                                int K)
{
    // Store the length of the string
    int N = str.Length;
 
    // Initialize a prefix sum array
    int []pref = new int[N];
 
    // Loop through the string to
    // create the prefix sum array
    for (int i = 0; i < N; i++)
    {
 
        // Store 1 at the index
        // if it is a vowel
        if (str[i] == 'a' ||
            str[i] == 'e' ||
            str[i] == 'i' ||
            str[i] == 'o' ||
            str[i] == 'u')
            pref[i] = 1;
 
        // Otherwise, store 0
        else
            pref[i] = 0;
 
        // Process the prefix array
        if (i != 0)
            pref[i] += pref[i - 1];
    }
 
    // Initialize the variable to store
    // maximum count of vowels
    int maxCount = pref[K - 1];
 
    // Initialize the variable
    // to store substring
    // with maximum count of vowels
    string res = str.Substring(0, K);
 
    // Loop through the prefix array
    for (int i = K; i < N; i++)
    {
 
        // Store the current
        // count of vowels
        int currCount = pref[i] -
                        pref[i - K];
 
        // Update the result if current count
        // is greater than maximum count
        if (currCount > maxCount)
        {
            maxCount = currCount;
            res = str.Substring(i - K + 1, K);
        }
 
        // Update lexicographically smallest
        // substring if the current count
        // is equal to the maximum count
        else if (currCount == maxCount)
        {
            string temp = str.Substring(i - K + 1, K);
 
            if (string.Compare(temp, res) == -1)
                res = temp;
        }
    }
 
    // Return the result
    return res;
}
 
// Driver Code
public static void Main()
{
    string str = "ceebbaceeffo";
    int K = 3;
 
    Console.Write(maxVowelSubString(str, K));
}
}
 
// This code is contributed by Code_Mech


Javascript




<script>
 
// Javascript program to find
// lexicographically smallest
// K-length substring containing
// maximum number of vowels
 
// Function that prints the
// lexicographically smallest
// K-length substring containing
// maximum number of vowels
function maxVowelSubString(str, K)
{
    // St||e the length of the string
    var N = str.length;
 
    // Initialize a prefix sum array
    var pref = Array(N);
 
    // Loop through the string to
    // create the prefix sum array
    for(var i = 0; i < N; i++) {
 
        // St||e 1 at the index
        // if it is a vowel
        if (str[i] == 'a'
            || str[i] == 'e'
            || str[i] == 'i'
            || str[i] == 'o'
            || str[i] == 'u')
            pref[i] = 1;
 
        // Otherwise, st||e 0
        else
            pref[i] = 0;
 
        // Process the prefix array
        if (i)
            pref[i] += pref[i - 1];
    }
 
    // Initialize the variable to st||e
    // maximum count of vowels
    var maxCount = pref[K - 1];
 
    // Initialize the variable
    // to st||e substring
    // with maximum count of vowels
    var res = str.substring(0, K);
 
    // Loop through the prefix array
    for (var i = K; i < N; i++) {
 
        // St||e the current
        // count of vowels
        var currCount
            = pref[i]
              - pref[i - K];
 
        // Update the result if current count
        // is greater than maximum count
        if (currCount > maxCount) {
 
            maxCount = currCount;
            res = str.substring(i - K + 1, i - 1);
        }
 
        // Update lexicographically smallest
        // substring if the current count
        // is equal to the maximum count
        else if (currCount == maxCount) {
 
            var temp
                = str.substring(
                    i - K + 1, i + 1);
 
            if (temp < res)
                res = temp;
        }
    }
 
    // Return the result
    return res;
}
 
// Driver Program
var str = "ceebbaceeffo";
var K = 3;
document.write( maxVowelSubString(str, K));
 
 
</script>


Output

ace







Time Complexity: O(N)
Auxiliary Space: O(N), where N is the length of the given string.
 

Time Optimized Approach :

we are using sliding window concept by means of mapping (map stl cpp).

let’s see approach/algorithm:

  •  first declare a map.
  • go on traversing and mapping each character.
  • if i>=k then remove i-kth element in map then.
  • count all vowels in substr or map.
  • take max of count if count is greater then max then traverse over string (i-k)+1 to i then store substr.

C++




#include <iostream>
#include <bits/stdc++.h>
using namespace std;
 
 bool isVowel(char ch){
        return (ch=='a'||ch=='e'||ch=='i'||ch=='o'||ch=='u');
  }
 
int main() {
      string s="geeksforgeeks";
      int k=4;
      unordered_map<char,int>mp;
      int maxelement=INT_MIN;
      string res;
      for(int i=0;i<s.size();i++){
            mp[s[i]]++;
            int cnt=0;string temp="";
            if(i>=k){
                --mp[s[i-k]];
            }
            for(auto &it:mp){
                if(isVowel(it.first)){
                  cnt+=it.second;
                }
            }
        if(maxelement<cnt&&i>=k){
           maxelement=cnt;
           temp=s.substr((i-k)+1,i);
          // for(int j=(i-k)+1;j<=i;j++)temp.push_back(s[j]);
           res=temp;
        }
      }
     cout<<res<<endl;
     cout<<maxelement<<endl;
    return 0;
  //code and approach contributed by Sanket Gode.
}


Java




import java.util.HashMap;
import java.util.Map;
 
public class Main {
    public static boolean isVowel(char ch) {
        return (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u');
    }
 
    public static void main(String[] args) {
        String s = "geeksforgeeks";
        int k = 4;
        Map<Character, Integer> mp = new HashMap<>();
        int maxElement = Integer.MIN_VALUE;
        String res = "";
 
        for (int i = 0; i < s.length(); i++) {
            mp.put(s.charAt(i), mp.getOrDefault(s.charAt(i), 0) + 1);
            int cnt = 0;
            String temp = "";
 
            if (i >= k) {
                char removedChar = s.charAt(i - k);
                mp.put(removedChar, mp.get(removedChar) - 1);
                if (mp.get(removedChar) == 0) {
                    mp.remove(removedChar);
                }
            }
 
            for (Map.Entry<Character, Integer> entry : mp.entrySet()) {
                if (isVowel(entry.getKey())) {
                    cnt += entry.getValue();
                }
            }
 
            if (maxElement < cnt && i >= k) {
                maxElement = cnt;
                temp = s.substring(i - k + 1, i + 1);
                res = temp;
            }
        }
 
        System.out.println(res);
        System.out.println(maxElement);
    }
}


Python3




def isVowel(ch):
    return ch == 'a' or ch == 'e' or ch == 'i' or ch == 'o' or ch == 'u'
 
s = "geeksforgeeks"
k = 4
mp = {}
maxelement = float('-inf')
res = ""
for i in range(len(s)):
    if s[i] not in mp:
        mp[s[i]] = 0
    mp[s[i]] += 1
    cnt = 0
    temp = ""
    if i >= k:
        mp[s[i-k]] -= 1
        if mp[s[i-k]] == 0:
            del mp[s[i-k]]
    for key in mp:
        if isVowel(key):
            cnt += mp[key]
    if maxelement < cnt and i >= k:
        maxelement = cnt
        temp = s[(i-k+1):(i+1)]
        res = temp
 
print(res)
print(maxelement)


C#




using System;
using System.Collections.Generic;
using System.Linq;
 
class Program
{
    // Function to check if a character is a vowel
    static bool IsVowel(char ch)
    {
        return (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u');
    }
 
    static void Main()
    {
        string s = "geeksforgeeks";
        int k = 4;
        Dictionary<char, int> mp = new Dictionary<char, int>(); // Create a dictionary to store character frequencies
        int maxelement = int.MinValue;
        string res = "";
 
        for (int i = 0; i < s.Length; i++)
        {
            // Update character frequency in the dictionary
            if (!mp.ContainsKey(s[i]))
                mp[s[i]] = 0;
             
            mp[s[i]]++;
 
            int cnt = 0; // Initialize a count for vowel frequencies
            string temp = ""; // Initialize a temporary string to store the current substring
 
            if (i >= k)
            {
                char toRemove = s[i - k];
                mp[toRemove]--; // Reduce the frequency of the character being removed
                if (mp[toRemove] == 0)
                    mp.Remove(toRemove); // Remove the character from the dictionary if its frequency becomes zero
            }
 
            // Calculate the count of vowels in the current substring
            foreach (var item in mp)
            {
                if (IsVowel(item.Key))
                {
                    cnt += item.Value;
                }
            }
 
            // Update the result if the current substring has more vowels
            if (maxelement < cnt && i >= k)
            {
                maxelement = cnt;
                temp = s.Substring(i - k + 1, k);
                res = temp;
            }
        }
 
        // Print the result and the maximum vowel count
        Console.WriteLine(res);
        Console.WriteLine(maxelement);
    }
}


Javascript




function isVowel(ch){
        return (ch=='a'||ch=='e'||ch=='i'||ch=='o'||ch=='u');
  }
 
let s="geeksforgeeks";
let k=4;
let mp=new Map();
let maxelement=Number.MIN_VALUE;
let res="";
for(let i=0;i<s.length;i++){
    if (!mp.has(s[i])) {
        mp.set(s[i], 0);
    }
    mp.set(s[i], mp.get(s[i]) + 1);
    let cnt=0;
    let temp="";
    if(i>=k){
        const charToRemove = s[i - k];
        mp.set(charToRemove, mp.get(charToRemove) - 1);
        if (mp.get(charToRemove) === 0) {
            mp.delete(charToRemove);
        }
    }
    for (const [key, value] of mp) {
        if (isVowel(key)) {
            cnt += value;
        }
    }
 
    if(maxelement<cnt && i>=k){
       maxelement=cnt;
       temp=s.substring((i-k)+1,i+1);
      // for(int j=(i-k)+1;j<=i;j++)temp.push_back(s[j]);
       res=temp;
    }
}
console.log(res);
console.log(maxelement);


Output

eeks
2







Complexity Analysis:

 Time Complexity : O(n*k).

 Space Complexity : O(k).

Space Optimized Approach :

Instead of storing prefix sums, we can use a sliding window and update our result at each maximum.

C++




#include <iostream>
using namespace std;
 
// Helper function to check if a character is a vowel
bool isVowel(char c)
{
    return c == 'a' or c == 'e' or c == 'i' or c == 'o'
           or c == 'u';
}
 
// Function to find the maximum vowel substring
string maxVowelSubstring(string s, int k)
{
    int maxCount = 0; // initialize maxCount as 0
    string res = s.substr(
        0, k); // and result as first substring of size k
    for (int i = 0, count = 0; i < s.size();
         i++) // iterate through the string
    {
        if (isVowel(
                s[i])) // if current character is a vowel
            count++; // then increase count
        if (i >= k
            and isVowel(
                s[i - k])) // if character that is leaving
                           // the window is a vowel
            count--; // then decrease count
 
        if (count > maxCount) // if we get a substring
                              // having more vowels
        {
            maxCount = count; // update count
            if (i >= k)
                res = s.substr(i - k + 1,
                               k); // and update result
        }
        if (count == maxCount
            and i >= k) // if we get a substring with same
                        // maximum number of vowels
        {
            string t = s.substr(i - k + 1, k);
            if (t < res) // then check if it is
                         // lexicographically smaller than
                         // current result and update it
                res = t;
        }
    }
    return res;
}
 
// Driver code
int main()
{
    string str = "geeksforgeeks";
    int k = 4;
    cout << maxVowelSubstring(str, k);
    return 0;
}


Java




/*package whatever //do not write package name here */
import java.io.*;
 
class GFG {
 
  static boolean isVowel(char c){
    return c == 'a' || c == 'e' || c == 'i' || c == 'o'
      || c == 'u';
  }
 
  // Function to find the maximum vowel subString
  static String maxVowelSubString(String s, int k)
  {
    int maxCount = 0; // initialize maxCount as 0
    String res = s.substring(0, k); // and result as first subString of size k
    for (int i = 0, count = 0; i < s.length();i++) // iterate through the String
    {
      if (isVowel(s.charAt(i))) // if current character is a vowel
        count++; // then increase count
      if (i >= k && isVowel(s.charAt(i - k))) // if character that is leaving
        // the window is a vowel
        count--; // then decrease count
 
      if (count > maxCount) // if we get a subString
        // having more vowels
      {
        maxCount = count; // update count
        if (i >= k)
          res = s.substring(i - k + 1,i + 1); // and update result
      }
      if (count == maxCount && i >= k) // if we get a subString with same
        // maximum number of vowels
      {
        String t = s.substring(i - k + 1, i + 1);
        if (t.compareTo(res) < 0){ // then check if it is
          // lexicographically smaller than
          // current result and update it
          res = t;
        }
      }
    }
    return res;
  }
 
  public static void main (String[] args) {
    String str = "geeksforgeeks";
    int k = 4;
    System.out.println(maxVowelSubString(str, k));
  }
}
 
// This code is contributed by shinjanpatra.


Python3




# Helper function to check if a character is a vowel
def isVowel(c):
   return (c == 'a' or c == 'e' or c == 'i' or c == 'o' or c == 'u')
     
# Function to find the maximum vowel substring
def maxVowelSubstring(s, k):
 
   # initialize maxCount as 0
   maxCount = 0
   
   # and result as first substring of size k
   res = s[0:k]
   
   # iterate through the string
   count = 0
   for i in range(len(s)):
       
      # if current character is a vowel
      if (isVowel(s[i])):
         count += 1 # then increase count
                 
         # if character that is leaving 
      if (i >= k and isVowel(s[i - k])): # the window is a vowel
         count -= 1 # then decrease count
 
      if (count > maxCount): # if we get a substring
                                  # having more vowels
         maxCount = count # update count
         if (i >= k):
             
            # and update result
            res = s[i - k + 1: i + 1]
             
            # if we get a substring with same
      if (count == maxCount and i >= k):
                            # maximum number of vowels
         t = s[i - k + 1: i+1]
         if (t < res): # then check if it is
                             # lexicographically smaller than
                             # current result and update it
            res = t
   return res
     
# driver code
str = "geeksforgeeks"
k = 4
print(maxVowelSubstring(str, k))
 
# This code is contributed by shinjanpatra


C#




// C# code for above approach
using System;
 
class GFG
{
    static bool IsVowel(char c)
    {
        return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u';
    }
 
    // Function to find the maximum vowel subString
    static string maxVowelSubString(string s, int k)
    {
        int maxCount = 0; // initialize maxCount as 0
        string res = s.Substring(0, k); // and result as first subString of size k
        for (int i = 0, count = 0; i < s.Length; i++) // iterate through the String
        {
            if (IsVowel(s[i])) // if current character is a vowel
                count++; // then increase count
            if (i >= k && IsVowel(s[i - k])) // if character that is leaving
                                            // the window is a vowel
                count--; // then decrease count
 
            if (count > maxCount) // if we get a subString
                                  // having more vowels
            {
                maxCount = count; // update count
                if (i >= k)
                    res = s.Substring(i - k + 1, k); // and update result
            }
            if (count == maxCount && i >= k) // if we get a subString with same
                                             // maximum number of vowels
            {
                string t = s.Substring(i - k + 1, k);
                if (string.Compare(t, res) < 0) // then check if it is
                // lexicographically smaller than
                // current result and update it
                {
                    res = t;
                }
            }
        }
        return res;
    }
 
    static void Main(string[] args)
    {
        string str = "geeksforgeeks";
        int k = 4;
        Console.WriteLine(maxVowelSubString(str, k));
    }
}
 
// This code is contributed by Pushpesh Raj.


Javascript




<script>
 
    // Helper function to check if a character is a vowel
    function isVowel(c)
    {
        return (c == 'a' || c == 'e' || c == 'i' || c == 'o'
               || c == 'u');
    }
     
    // Function to find the maximum vowel substring
    function maxVowelSubstring(s, k)
    {
        // initialize maxCount as 0
        let maxCount = 0;
        // and result as first substring of size k
        let res = s.substr(0, k);
        // iterate through the string
        for (let i = 0, count = 0; i < s.length; i++)
        {
            // if current character is a vowel
            if (isVowel(s[i]))
                count++; // then increase count
                 
            // if character that is leaving 
            if (i >= k && isVowel(s[i - k]))
                               // the window is a vowel
                count--; // then decrease count
 
            if (count > maxCount) // if we get a substring
                                  // having more vowels
            {
                maxCount = count; // update count
                if (i >= k)
                    // and update result
                    res = s.substr(i - k + 1, k);
            }
            // if we get a substring with same
            if (count == maxCount && i >= k)
                            // maximum number of vowels
            {
                let t = s.substr(i - k + 1, k);
                if (t < res) // then check if it is
                             // lexicographically smaller than
                             // current result and update it
                    res = t;
            }
        }
        return res;
    }
     
    let str = "geeksforgeeks";
    let k = 4;
    document.write(maxVowelSubstring(str, k));
   
</script>


Output

eeks







Time Complexity: O(N) 
Space Complexity: O(1) 



Last Updated : 06 Oct, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads