Split a String into two Substring such that the sum of unique characters is maximum
Given a string str, the task is to partition the string into two substrings such that the sum of unique characters of both substrings is the maximum possible.
Examples:
Input: str = “abcabcd”
Output: 7
Explanation: Partition the given string into “abc” and “abcd”, the sum of unique characters is 3 + 4 = 7 which is maximum possible.
Input: str = “aaaaa”
Output: 2
Explanation: Partition the given string into “aa” and “aaa”, the sum of unique characters is 1 + 1 = 2 which is maximum possible. Given string can be partitioned into many other ways but this partition gives the maximum sum of unique characters.
Approach: This problem can easily be solved using prefix and suffix arrays.
We can create a prefix array which will store the count of unique characters starting from index 0 to last index of the string. Similarly, We can create a suffix array which will store the count of unique characters starting from the last index to 0th index. Here, set can be used to check if the current character appeared before in the iterated string or not. We can calculate the maximum sum by doing prefix[i-1] + suffix[i] for each 1 <= i < n. Take prefix[i-1] + suffix[i] so that intersecting point never counts.
Follow the steps mentioned below to implement the idea:
- Declare two arrays of prefix and suffix
- Declare two sets that store the visited characters so far.
- Store prefix[i] = prefix[i-1] if the current character has already appeared, else prefix[i] = prefix[i-1] + 1
- Store suffix[i] = suffix[i] if the current character has already appeared, else suffix[i] = suffix[i+1] + 1.
- Declare a variable maxi = -1 which stores the maximum sum
- Iterate through the array and compare the sum of prefix[i-1] + suffix[i] with maxi in each iteration.
- Return maxi.
Below is the implementation of the above approach.
C++
#include <bits/stdc++.h>
using namespace std;
int unique_characters(string str, int n)
{
set< char > s1;
set< char > s2;
vector< int > prefix(n);
vector< int > suffix(n);
prefix[0] = 1;
suffix[n - 1] = 1;
s1.insert(str[0]);
s2.insert(str[n - 1]);
for ( int i = 1; i < n; i++) {
if (s1.find(str[i]) != s1.end()) {
prefix[i] = prefix[i - 1];
}
else {
prefix[i] = prefix[i - 1] + 1;
s1.insert(str[i]);
}
}
for ( int i = n - 2; i >= 0; i--) {
if (s2.find(str[i]) != s2.end()) {
suffix[i] = suffix[i + 1];
}
else {
suffix[i] = suffix[i + 1] + 1;
s2.insert(str[i]);
}
}
int maxi = -1;
for ( int i = 1; i < n; i++) {
maxi = max(maxi, prefix[i - 1] + suffix[i]);
}
return maxi;
}
int main()
{
string str = "abcabcd" ;
int n = str.length();
cout << "Maximum sum is " << unique_characters(str, n);
return 0;
}
|
Java
import java.util.*;
class GFG {
public static void main(String[] args)
{
String str = "abcabcd" ;
int n = str.length();
System.out.println( "Maximum sum is "
+ (unique_characters(str, n)));
}
public static int unique_characters(String str, int n)
{
TreeSet<Character> s1 = new TreeSet<>();
TreeSet<Character> s2 = new TreeSet<>();
int [] prefix = new int [n];
int [] suffix = new int [n];
prefix[ 0 ] = 1 ;
suffix[n - 1 ] = 1 ;
s1.add(str.charAt( 0 ));
s2.add(str.charAt(n - 1 ));
for ( int i = 1 ; i < n; i++) {
if ((s1.contains(str.charAt(i)))
&& str.charAt(i) != s1.last()) {
prefix[i] = prefix[i - 1 ];
}
else {
prefix[i] = prefix[i - 1 ] + 1 ;
s1.add(str.charAt(i));
}
}
for ( int i = n - 2 ; i >= 0 ; i--) {
if ((s2.contains(str.charAt(i)))
&& str.charAt(i) != s2.last()) {
suffix[i] = suffix[i + 1 ];
}
else {
suffix[i] = suffix[i + 1 ] + 1 ;
s2.add(str.charAt(i));
}
}
int maxi = - 1 ;
for ( int i = 1 ; i < n; i++) {
maxi
= Math.max(maxi, prefix[i - 1 ] + suffix[i]);
}
return maxi;
}
}
|
Python3
def unique_characters( str , n):
s1 = set ()
s2 = set ()
prefix = [ 0 ] * n
suffix = [ 0 ] * n
prefix[ 0 ] = 1
suffix[n - 1 ] = 1
s1.add( str [ 0 ])
s2.add( str [n - 1 ])
for i in range ( 1 , n):
if str [i] in s1:
prefix[i] = prefix[i - 1 ]
else :
prefix[i] = prefix[i - 1 ] + 1
s1.add( str [i])
for i in range (n - 2 , - 1 , - 1 ):
if str [i] in s2:
suffix[i] = suffix[i + 1 ]
else :
suffix[i] = suffix[i + 1 ] + 1
s2.add( str [i])
maxi = - 1
for i in range ( 1 , n):
maxi = max (maxi, prefix[i - 1 ] + suffix[i])
return maxi
if __name__ = = "__main__" :
str = "abcabcd"
n = len ( str )
print ( "Maximum sum is " , unique_characters( str , n))
|
C#
using System;
using System.Collections.Generic;
public class GFG {
static int UniqueCharacters( string str, int n)
{
SortedSet< char > s1 = new SortedSet< char >();
SortedSet< char > s2 = new SortedSet< char >();
int [] prefix = new int [n];
int [] suffix = new int [n];
prefix[0] = 1;
suffix[n - 1] = 1;
s1.Add(str[0]);
s2.Add(str[n - 1]);
for ( int i = 1; i < n; i++) {
if ((s1.Contains(str[i])) && str[i] != s1.Max) {
prefix[i] = prefix[i - 1];
}
else {
prefix[i] = prefix[i - 1] + 1;
s1.Add(str[i]);
}
}
for ( int i = n - 2; i >= 0; i--) {
if ((s2.Contains(str[i])) && str[i] != s2.Max) {
suffix[i] = suffix[i + 1];
}
else {
suffix[i] = suffix[i + 1] + 1;
s2.Add(str[i]);
}
}
int maxi = -1;
for ( int i = 1; i < n; i++) {
maxi
= Math.Max(maxi, prefix[i - 1] + suffix[i]);
}
return maxi;
}
static public void Main()
{
string str = "abcabcd" ;
int n = str.Length;
Console.WriteLine( "Maximum sum is "
+ (UniqueCharacters(str, n)));
}
}
|
Javascript
function uniqueCharacters(str, n) {
var s1 = new Set();
var s2 = new Set();
var prefix = new Array(n);
var suffix = new Array(n);
prefix[0] = 1;
suffix[n - 1] = 1;
s1.add(str[0]);
s2.add(str[n - 1]);
for ( var i = 1; i < n; i++) {
if (s1.has(str[i])) {
prefix[i] = prefix[i - 1];
}
else {
prefix[i] = prefix[i - 1] + 1;
s1.add(str[i]);
}
}
for ( var i = n - 2; i >= 0; i--) {
if (s2.has(str[i])) {
suffix[i] = suffix[i + 1];
}
else {
suffix[i] = suffix[i + 1] + 1;
s2.add(str[i]);
}
}
var maxi = -1;
for ( var i = 1; i < n; i++) {
maxi = Math.max(maxi, prefix[i - 1] + suffix[i]);
}
return maxi;
}
var str = "abcabcd" ;
var n = str.length;
console.log( "Maximum sum is " + uniqueCharacters(str, n));
|
Output
Maximum value is 7
Time Complexity: O(N)
Auxiliary Space: O(N)
Efficient Approach: To solve this problem, we will use two Hash Maps and do the below steps:
- Firstly, make a frequency map of characters and store in Hash Map characters.
- Now, we will traverse from the start of the given string str, also we will maintain another frequency map using Hash Map freq.
- While traversing, we will keep track of the maximum sum of the sizes of characters and freq, whenever our maximum value changes we will change our maximum pointer.
- At last, we will return the maximum possible answer.
Implementation of the approach:
C++
#include <bits/stdc++.h>
#include <string>
#include <unordered_map>
using namespace std;
int maxUniqueCharSubstring(string str, int N)
{
unordered_map< char , int > characters;
unordered_map< char , int > freq;
for ( int i = 0; i < N; i++) {
characters[str[i]]++;
}
int max = INT_MIN;
for ( int i = 0; i < N; i++) {
int totalChar = (characters.size() + freq.size());
if (max < totalChar) {
max = totalChar;
}
freq[str[i]]++;
characters[str[i]]--;
if (characters[str[i]] == 0) {
characters.erase(str[i]);
}
}
return max;
}
int main()
{
string str = "abcabcd" ;
int N = str.length();
cout << "Maximum sum is "
<< maxUniqueCharSubstring(str, N) << endl;
return 0;
}
|
Java
import java.util.*;
class GFG {
public static void main(String[] args)
{
String str = "abcabcd" ;
int N = str.length();
System.out.println(
"Maximum sum is "
+ maxUniqueCharSubstring(str, N));
}
public static int maxUniqueCharSubstring(String str,
int N)
{
Map<Character, Integer> characters
= new HashMap<>();
Map<Character, Integer> freq = new HashMap<>();
for ( int i = 0 ; i < N; i++) {
characters.put(
str.charAt(i),
characters.getOrDefault(str.charAt(i), 0 )
+ 1 );
}
int max = Integer.MIN_VALUE;
for ( int i = 0 ; i < N; i++) {
if (max < characters.size() + freq.size()) {
max = characters.size() + freq.size();
}
freq.put(str.charAt(i),
freq.getOrDefault(str.charAt(i), 0 )
+ 1 );
characters.put(str.charAt(i),
characters.get(str.charAt(i))
- 1 );
if (characters.get(str.charAt(i)) == 0 )
characters.remove(str.charAt(i));
}
return max;
}
}
|
Python3
def maxUniqueCharSubstring(string):
characters = {}
freq = {}
for i in string:
if i in characters:
characters[i] + = 1
else :
characters[i] = 1
max_len = float ( '-inf' )
for i in range ( len (string)):
if max_len < len (characters) + len (freq):
max_len = len (characters) + len (freq)
if string[i] in freq:
freq[string[i]] + = 1
else :
freq[string[i]] = 1
characters[string[i]] = characters[string[i]] - 1
if characters[string[i]] = = 0 :
del characters[string[i]]
return max_len
string = "abcabcd"
print ( "Maximum sum is" , maxUniqueCharSubstring(string))
|
C#
using System;
using System.Collections.Generic;
public class GFG {
public static int maxUniqueCharSubstring( string str,
int N)
{
Dictionary< char , int > characters
= new Dictionary< char , int >();
Dictionary< char , int > freq
= new Dictionary< char , int >();
for ( int i = 0; i < N; i++) {
if (characters.ContainsKey(str[i]))
characters[str[i]] += 1;
else
characters.Add(str[i], 1);
}
int max = int .MinValue;
for ( int i = 0; i < N; i++) {
if (max < characters.Count + freq.Count) {
max = characters.Count + freq.Count;
}
if (freq.ContainsKey(str[i]))
freq[str[i]] += 1;
else
freq.Add(str[i], 1);
characters[str[i]] -= 1;
if (characters[str[i]] == 0)
characters.Remove(str[i]);
}
return max;
}
static public void Main()
{
string str = "abcabcd" ;
int N = str.Length;
Console.WriteLine( "Maximum sum is "
+ maxUniqueCharSubstring(str, N));
}
}
|
Javascript
function maxUniqueCharSubstring(str, N)
{
let characters = new Map();
let freq = new Map();
for (let i = 0; i < N; i++) {
characters.set(str[i], (characters.get(str[i]) || 0) + 1);
}
let max = Number.MIN_SAFE_INTEGER;
for (let i = 0; i < N; i++) {
let totalChar = (characters.size + freq.size);
if (max < totalChar) {
max = totalChar;
}
freq.set(str[i], (freq.get(str[i]) || 0) + 1);
characters.set(str[i], (characters.get(str[i]) || 0) - 1);
if (characters.get(str[i]) === 0) {
characters. delete (str[i]);
}
}
return max;
}
let str = "abcabcd" ;
let N = str.length;
console.log( "Maximum sum is " + maxUniqueCharSubstring(str, N));
|
Output:
Maximum sum is 7
Time Complexity: O(N)
Auxiliary Space: Constant space is used as there can be only at most 26 characters stored in hash map.
Last Updated :
11 Apr, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...