Given a string str, the task is to find the substring of length K which occurs the maximum number of times. If more than one string occurs maximum number of times, then print the lexicographically smallest substring.
Examples:
Input: str = “bbbbbaaaaabbabababa”, K = 5
Output: ababa
Explanation:
The substrings of length 5 from the above strings are {bbbbb, bbbba, bbbaa, bbaaa, baaaa, aaaaa, aaaab, aaabb, aabba, abbab, bbaba, babab, ababa, babab, ababa}.
Among all of them, substrings {ababa, babab} occurs the maximum number of times(= 2).
The lexicographically smallest string from {ababa, babab} is ababa.
Therefore, “ababa” is the required answer.
Input: str = “heisagoodboy”, K = 5
Output: agood
Explanation:
The substrings of length 5 from the above string are {heisa, eisag, isago, sagoo, agood, goodb, oodbo, odboy}.
All of them occur only once. But the lexicographically smallest string among them is “agood”.
Therefore, “agood” is the required answer.
Naive Approach: The simplest approach to solve the problem is to generate all the substrings of size K from the given string and store the frequency of each substring in a Map. Then, traverse the Map and find the lexicographically smallest substring which occurs maximum number of times and print it.
C++
#include <bits/stdc++.h>
using namespace std;
string maximumOccurringString(string str, int k)
{
string curr= "" ;
int i=0, j=0, n=str.length();
map<string, int >mp;
while (j<n){
curr+=str[j];
if (j-i+1 < k){
j++;
}
else if (j-i+1 == k){
mp[curr]++;
curr.erase(0, 1);
i++;
j++;
}
}
int cnt=-1;
string ans;
for ( auto x : mp){
int c = x.second;
if (c > cnt){
ans = x.first;
cnt =c;
}
}
return ans;
}
int main()
{
string str = "bbbbbaaaaabbabababa" ;
int k = 5;
cout << maximumOccurringString(str, k);
return 0;
}
|
Java
import java.util.*;
public class Main {
static String maximumOccurringString(String str, int k) {
String curr = "" ;
int i = 0 , j = 0 , n = str.length();
TreeMap<String, Integer> mp = new TreeMap<>();
while (j < n) {
curr += str.charAt(j);
if (j - i + 1 < k) {
j++;
}
else if (j - i + 1 == k) {
mp.put(curr, mp.getOrDefault(curr, 0 ) + 1 );
curr = curr.substring( 1 );
i++;
j++;
}
}
int cnt = - 1 ;
String ans = "" ;
for (Map.Entry<String, Integer> x : mp.entrySet()) {
int c = x.getValue();
if (c > cnt) {
ans = x.getKey();
cnt = c;
}
}
return ans;
}
public static void main(String[] args) {
String str = "bbbbbaaaaabbabababa" ;
int k = 5 ;
System.out.println(maximumOccurringString(str, k));
}
}
|
Python3
def maximum_occuring_string(string, k):
curr = ""
n = len (string)
i = j = 0
mp = {}
while j < n:
curr + = string[j]
if j - i + 1 < k:
j + = 1
elif j - i + 1 = = k:
if curr in mp:
mp[curr] + = 1
else :
mp[curr] = 1
curr = curr[ 1 :]
i + = 1
j + = 1
cnt = - 1
ans = ""
for x in mp:
c = mp[x]
if c > cnt or (c = = cnt and x < ans):
ans = x
cnt = c
return ans
string = "bbbbbaaaaabbabababa"
k = 5
print (maximum_occuring_string(string, k))
|
C#
using System;
using System.Collections.Generic;
class Program
{
static string MaximumOccurringString( string str, int k)
{
string curr = "" ;
int i = 0, j = 0, n = str.Length;
SortedDictionary< string , int > mp = new SortedDictionary< string , int >();
while (j < n)
{
curr += str[j];
if (j - i + 1 < k)
{
j++;
}
else if (j - i + 1 == k)
{
if (mp.ContainsKey(curr))
{
mp[curr]++;
}
else
{
mp.Add(curr, 1);
}
curr = curr.Substring(1);
i++;
j++;
}
}
int cnt = -1;
string ans = "" ;
foreach ( var x in mp)
{
int c = x.Value;
if (c > cnt)
{
ans = x.Key;
cnt = c;
}
}
return ans;
}
static void Main()
{
string str = "bbbbbaaaaabbabababa" ;
int k = 5;
Console.WriteLine(MaximumOccurringString(str, k));
}
}
|
Javascript
function MaximumOccurringString(str, k) {
let curr = "" ;
let i = 0, j = 0, n = str.length;
let mp = new Map();
while (j < n) {
curr += str[j];
if (j - i + 1 < k) {
j++;
}
else if (j - i + 1 == k) {
if (mp.has(curr)) {
mp.set(curr, mp.get(curr) + 1);
}
else {
mp.set(curr, 1);
}
curr = curr.substring(1);
i++;
j++;
}
}
let cnt = -1;
let ans = "" ;
let keys = Array.from(mp.keys())
keys.sort()
for (let key of keys) {
let c = mp.get(key);
if (c > cnt) {
ans = key;
cnt = c;
}
}
return ans;
}
let str = "bbbbbaaaaabbabababa" ;
let k = 5;
console.log(MaximumOccurringString(str, k));
|
Time Complexity: O(N*( K + log K))
Auxiliary Space: O(N * K)
Efficient Approach: To optimize the above approach, the idea is to use Sliding Window technique. Consider a window of size
K to generate all substrings of length K and count the frequency of a substring generated in a Map. Traverse the map and find the substring that occurs maximum number of times and print it. If several of them exist, then print the lexicographically smallest substring.
Below is the implementation of the above approach.
C++
#include <bits/stdc++.h>
using ll = long long int ;
using namespace std;
void maximumOccurringString(string s, ll K)
{
map<deque< char >, ll> M;
ll i;
deque< char > D;
for (i = 0; i < K; i++) {
D.push_back(s[i]);
}
M[D]++;
D.pop_front();
for (ll j = i; j < s.size(); j++) {
D.push_back(s[j]);
M[D]++;
D.pop_front();
}
ll maxi = INT_MIN;
deque< char > ans;
for ( auto it : M) {
if (it.second > maxi) {
maxi = it.second;
ans = it.first;
}
}
for (ll i = 0; i < ans.size(); i++) {
cout << ans[i];
}
}
int main()
{
string s = "bbbbbaaaaabbabababa" ;
ll K = 5;
maximumOccurringString(s, K);
return 0;
}
|
Java
import java.util.*;
public class Main {
public static void maximumOccurringString(String s,
int K)
{
Map<String, Integer> M = new HashMap<>();
Deque<Character> D = new LinkedList<>();
for ( int i = 0 ; i < K; i++) {
D.addLast(s.charAt(i));
}
M.put(D.toString(),
M.getOrDefault(D.toString(), 0 ) + 1 );
D.removeFirst();
for ( int j = K; j < s.length(); j++) {
D.addLast(s.charAt(j));
M.put(D.toString(),
M.getOrDefault(D.toString(), 0 ) + 1 );
D.removeFirst();
}
int maxi = Integer.MIN_VALUE;
String ans = "" ;
for (String it : M.keySet()) {
if (M.get(it) > maxi) {
maxi = M.get(it);
ans = it;
}
}
for ( int i = 0 ; i < ans.length(); i++) {
char c = ans.charAt(i);
if (Character.isAlphabetic(c)) {
System.out.print(c);
}
}
}
public static void main(String[] args)
{
String s = "bbbbbaaaaabbabababa" ;
int K = 5 ;
maximumOccurringString(s, K);
}
}
|
Python3
from collections import deque, Counter, defaultdict
import sys
def maximumOccurringString(s, K):
M = {}
D = deque()
for i in range (K):
D.append(s[i])
M[ str ("".join( list (D)))] = M.get(
str ("".join( list (D))), 0 ) + 1
D.popleft()
for j in range (i, len (s)):
D.append(s[j])
M[ str ("".join( list (D)))] = M.get(
str ("".join( list (D))), 0 ) + 1
D.popleft()
maxi = - sys.maxsize - 1
ans = deque()
for it in M:
if (M[it] > = maxi):
maxi = M[it]
ans = it
for i in range ( len (ans)):
print (ans[i], end = "")
if __name__ = = '__main__' :
s = "bbbbbaaaaabbabababa"
K = 5
maximumOccurringString(s, K)
|
C#
using System;
using System.Collections.Generic;
namespace MaximumOccurringSubstring
{
class Program
{
static void maximumOccurringString( string s, long K)
{
Dictionary<Queue< char >, long > M = new Dictionary<Queue< char >, long >();
long i;
Queue< char > D = new Queue< char >();
for (i = 0; i < K; i++)
{
D.Enqueue(s[( int )i]);
}
M[D] = M.ContainsKey(D) ? M[D] + 1 : 1;
D.Dequeue();
for ( long j = i; j < s.Length; j++)
{
D.Enqueue(s[( int )j]);
M[D] = M.ContainsKey(D) ? M[D] + 1 : 1;
D.Dequeue();
}
long maxi = int .MinValue;
Queue< char > ans = new Queue< char >();
foreach ( var kvp in M)
{
if (kvp.Value > maxi)
{
maxi = kvp.Value;
ans = kvp.Key;
}
}
Console.Write( 'a' );
foreach ( var c in ans)
{
Console.Write(c);
}
}
static void Main( string [] args)
{
string s = "bbbbbaaaaabbabababa" ;
long K = 5;
maximumOccurringString(s, K);
}
}
}
|
Javascript
function maximumOccurringString(s, K) {
let M = {};
let D = [];
for (let i = 0; i < K; i++) {
D.push(s[i]);
}
M[D.join( '' )] = M[D.join( '' )] ? M[D.join( '' )] + 1 : 1;
D.shift();
for (let j = K; j < s.length; j++) {
D.push(s[j]);
M[D.join( '' )] = M[D.join( '' )] ? M[D.join( '' )] + 1 : 1;
D.shift();
}
let maxi = -Infinity;
let ans = [];
for (let it in M) {
if (M[it] >= maxi) {
maxi = M[it];
ans = it.split( '' );
}
}
console.log(ans.join( '' ));
}
let s = "bbbbbaaaaabbabababa" ;
let K = 5;
maximumOccurringString(s, K);
|
Time Complexity: O((N – K)*log(N – K))
Auxiliary Space: O(N – K)