Partition string into two substrings having maximum number of common non-repeating characters
Given a string str, the task is to find the maximum count of common non-repeating characters that can be obtained by partitioning the given string into two non-empty substrings.
Examples:
Input : str = “aabbca”
Output: 2
Explanation:
Partition the string into two substrings { { str[0], … str[2] }, { str[3], …, str[5] } }
The common non-repeating characters present in both the substrings are { ‘a’, ‘b’}
Therefore, the required output is 2.
Input: str = “aaaaaaaaaa”
Output: 1
Naive Approach: The simplest approach to solve this problem is to iterate over the characters of the string and partition the string into two non-empty substrings at every possible indices and count the number of common-repeating characters from the two substrings. Print the maximum count obtained.
Algorithm:
- Define a function named countCommonChar that takes two arguments – an integer index and a string S, and returns an integer value.
- Inside the function, initialize a counter variable cnt to zero.
- Create two sets, ls and rs, to store distinct characters in the left and right substrings respectively.
- Traverse the characters in the string S up to the given index and insert each character into the set ls.
- Traverse the characters in the string S from the given index up to the end of the string and insert each character into the set rs.
- Traverse the distinct characters in the set ls.
- For each character, check if it is present in the set rs. If yes, increment the counter variable cnt.
- Return the value of cnt.
- Define another function named partitionStringWithMaxCom that takes a string S as an argument and returns nothing.
- Inside the function, initialize a variable ans to zero.
- Traverse the characters in the string S from the second character to the second last character.
- For each character, call the function countCommonChar with the current index as the argument and store the returned value in a variable temp.
- Update the value of ans by taking the maximum of the current value of ans and temp.
- Print the value of ans.
- The main function reads the input string, calls the function partitionStringWithMaxCom with the input string as the argument, and returns 0.
Pseudocode:
countCommonChar(ind, S):
cnt = 0
ls = set()
rs = set()
for i = 0 to ind - 1:
ls.insert(S[i])
for i = ind to length(S) - 1:
rs.insert(S[i])
for v in ls:
if rs.count(v):
cnt = cnt + 1
return cnt
partitionStringWithMaxCom(S):
ans = 0
for i = 1 to length(S) - 2:
temp = countCommonChar(i, S)
ans = max(ans, temp)
print ans
main():
str = input from user
partitionStringWithMaxCom(str)
return 0
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int countCommonChar( int ind, string& S)
{
int cnt = 0;
set< char > ls;
set< char > rs;
for ( int i = 0; i < ind; ++i) {
ls.insert(S[i]);
}
for ( int i = ind; i < S.length();
++i) {
rs.insert(S[i]);
}
for ( auto v : ls) {
if (rs.count(v)) {
++cnt;
}
}
return cnt;
}
void partitionStringWithMaxCom(string& S)
{
int ans = 0;
for ( int i = 1; i < S.length(); ++i) {
ans = max(ans,
countCommonChar(i, S));
}
cout << ans << "\n" ;
}
int main()
{
string str = "aabbca" ;
partitionStringWithMaxCom(str);
return 0;
}
|
Java
import java.util.*;
class GFG{
static int countCommonChar( int ind, String S)
{
int cnt = 0 ;
HashSet<Character> ls = new HashSet<Character>();
HashSet<Character> rs = new HashSet<Character>();
for ( int i = 0 ; i < ind; ++i) {
ls.add(S.charAt(i));
}
for ( int i = ind; i < S.length();
++i) {
rs.add(S.charAt(i));
}
for ( char v : ls) {
if (rs.contains(v)) {
++cnt;
}
}
return cnt;
}
static void partitionStringWithMaxCom(String S)
{
int ans = 0 ;
for ( int i = 1 ; i < S.length(); ++i) {
ans = Math.max(ans,
countCommonChar(i, S));
}
System.out.print(ans+ "\n" );
}
public static void main(String[] args)
{
String str = "aabbca" ;
partitionStringWithMaxCom(str);
}
}
|
Python3
def countCommonChar(ind, S):
cnt = 0
ls = set ()
rs = set ()
for i in range (ind):
ls.add(S[i])
for i in range (ind, len (S)):
rs.add(S[i])
for v in ls:
if v in rs:
cnt + = 1
return cnt
def partitionStringWithMaxCom(S):
ans = 0
for i in range ( 1 , len (S)):
ans = max (ans, countCommonChar(i, S))
print (ans)
if __name__ = = "__main__" :
string = "aabbca"
partitionStringWithMaxCom(string)
|
C#
using System;
using System.Collections.Generic;
class GFG{
static int countCommonChar( int ind, String S)
{
int cnt = 0;
HashSet< char > ls = new HashSet< char >();
HashSet< char > rs = new HashSet< char >();
for ( int i = 0; i < ind; ++i)
{
ls.Add(S[i]);
}
for ( int i = ind; i < S.Length; ++i)
{
rs.Add(S[i]);
}
foreach ( char v in ls)
{
if (rs.Contains(v))
{
++cnt;
}
}
return cnt;
}
static void partitionStringWithMaxCom(String S)
{
int ans = 0;
for ( int i = 1; i < S.Length; ++i)
{
ans = Math.Max(ans,
countCommonChar(i, S));
}
Console.Write(ans + "\n" );
}
public static void Main(String[] args)
{
String str = "aabbca" ;
partitionStringWithMaxCom(str);
}
}
|
Javascript
<script>
function countCommonChar(ind, S)
{
var cnt = 0;
var ls = new Set();
var rs = new Set();
for ( var i = 0; i < ind; ++i) {
ls.add(S[i]);
}
for ( var i = ind; i < S.length;
++i) {
rs.add(S[i]);
}
ls.forEach(v => {
if (rs.has(v)) {
++cnt;
}
});
return cnt;
}
function partitionStringWithMaxCom(S)
{
var ans = 0;
for ( var i = 1; i < S.length; ++i) {
ans = Math.max(ans,
countCommonChar(i, S));
}
document.write( ans);
}
var str = "aabbca" ;
partitionStringWithMaxCom(str);
</script>
|
Time Complexity: O(N2)
Auxiliary Space: O(N)
Efficient Approach: To optimize the above approach, the idea is to use Hashing and Ordered Set to store the distinct characters of the string in sorted order. Follow the steps below to solve the problem:
- Initialize a variable, say res, to store the maximum count of common distinct characters present in both the substrings by partitioning the string into two substrings.
- Initialize a Map, say mp, to store the frequency of each distinct character of the string.
- Initialize an Ordered Set, say Q, to store the distinct characters of the string in sorted order.
- Iterate over characters of the string and for every ith character, decrement the frequency of str[i] and check if the frequency of mp[str[i]] is equal to 0 or not. If found to be false, then remove str[i] from the Ordered Set.
- Otherwise, insert str[i] in the ordered set and update res = max(res, X), where X is the count of elements in the ordered set.
- Finally, print the value of res.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_cxx;
using namespace __gnu_pbds;
template < typename T>
using ordered_set = tree<T, null_type, less<T>,
rb_tree_tag, tree_order_statistics_node_update>;
int countMaxCommonChar(string& S)
{
ordered_set< char > Q;
int res = 0;
map< char , int > freq;
for ( int i = 0; i < S.length(); i++) {
freq[S[i]]++;
}
for ( int i = 0; i < S.length(); i++) {
freq[S[i]]--;
if (!freq[S[i]]) {
Q.erase(S[i]);
}
else {
Q.insert(S[i]);
}
int curr = Q.size();
res = max(res, curr);
}
cout << res << "\n" ;
}
int main()
{
string str = "aabbca" ;
countMaxCommonChar(str);
return 0;
}
|
Java
import java.util.*;
class GFG{
static void countMaxCommonChar( char [] S)
{
LinkedHashSet<Character> Q = new LinkedHashSet<>();
int res = 1 ;
HashMap<Character, Integer> freq = new HashMap<>();
for ( int i = 0 ; i < S.length; i++)
{
if (freq.containsKey(S[i]))
{
freq.put(S[i], freq.get(S[i]) + 1 );
}
else
{
freq.put(S[i], 1 );
}
}
for ( int i = 0 ; i < S.length; i++)
{
if (freq.containsKey(S[i]))
{
freq.put(S[i], freq.get(S[i]) - 1 );
}
if (!freq.containsKey(S[i]))
{
Q.remove(S[i]);
}
else
{
Q.add(S[i]);
}
int curr = Q.size() - 1 ;
res = Math.max(res, curr);
}
System.out.print(res + "\n" );
}
public static void main(String[] args)
{
String str = "aabbca" ;
countMaxCommonChar(str.toCharArray());
}
}
|
Python3
from collections import Counter
from sortedcontainers import SortedSet
def countMaxCommonChar(S):
Q = SortedSet()
res = 0
freq = Counter(S)
for i in range ( len (S)):
freq[S[i]] - = 1
if freq[S[i]] = = 0 :
Q.discard(S[i])
else :
Q.add(S[i])
curr = len (Q)
res = max (res, curr)
print (res)
if __name__ = = '__main__' :
str = "aabbca"
countMaxCommonChar( str )
|
C#
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
class HelloWorld {
public static void countMaxCommonChar( char [] S)
{
SortedSet< char > Q = new SortedSet< char >();
int res = 1;
Dictionary < char , int > freq = new Dictionary < char , int > ();
for ( int i = 0; i < S.Length; i++)
{
if (freq.ContainsKey(S[i]) == true )
{
freq[S[i]] = freq[S[i]] + 1;
}
else
{
freq[S[i]] = 1;
}
}
for ( int i = 0; i < S.Length; i++)
{
if (freq.ContainsKey(S[i]))
{
freq[S[i]] = freq[S[i]] - 1;
}
if (!freq.ContainsKey(S[i]))
{
Q.Remove(S[i]);
}
else
{
Q.Add(S[i]);
}
int curr = Q.Count - 1;
res = Math.Max(res, curr);
}
Console.Write(res);
}
static void Main() {
string str = "aabbca" ;
countMaxCommonChar(str.ToCharArray());
}
}
|
Javascript
function countMaxCommonChar(S) {
let Q = new Set();
let res = 0;
let freq = new Map();
for (let i = 0; i < S.length; i++) {
if (freq.has(S[i])) {
freq.set(S[i], freq.get(S[i]) - 1);
} else {
freq.set(S[i], 1);
}
if (freq.get(S[i]) === 0) {
Q. delete (S[i]);
} else {
Q.add(S[i]);
}
let curr = Q.size;
res = Math.max(res, curr);
}
console.log(res);
}
let str = "aabbca" ;
countMaxCommonChar(str);
|
Time Complexity: O(N * log(N))
Auxiliary Space: O(N)
Last Updated :
18 Mar, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...