 Open in App
Not now

# Split a String into two Substring such that the sum of unique characters is maximum

• Last Updated : 28 Mar, 2023

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++

 `// C++ code for the above approach:` `#include ` `using` `namespace` `std;`   `// Function for finding out maximum value` `int` `unique_charcters(string str, ``int` `n)` `{`   `    ``// Declare set to check if the current` `    ``// character is previously` `    ``// appearing or not` `    ``set<``char``> s1;` `    ``set<``char``> s2;`   `    ``// Store the count of unique characters` `    ``// from starting index.` `    ``vector<``int``> prefix(n);`   `    ``// Store the count of unique characters` `    ``// from last index.` `    ``vector<``int``> suffix(n);` `    ``prefix = 1;` `    ``suffix[n - 1] = 1;` `    ``s1.insert(str);` `    ``s2.insert(str[n - 1]);`   `    ``// Storing the count of unique characters` `    ``// from starting index to last index` `    ``for` `(``int` `i = 1; i < n; i++) {`   `        ``// If the current character has` `        ``// appeared before, store` `        ``// previous value` `        ``if` `(s1.find(str[i]) != s1.end()) {` `            ``prefix[i] = prefix[i - 1];` `        ``}` `        ``else` `{` `            ``// else store previous value + 1.` `            ``prefix[i] = prefix[i - 1] + 1;` `            ``s1.insert(str[i]);` `        ``}` `    ``}`   `    ``// Storing the count of unique` `    ``// characters from last index` `    ``// to 0th index` `    ``for` `(``int` `i = n - 2; i >= 0; i--) {`   `        ``// If the current character has` `        ``// already appeared, store the` `        ``// value calculated for the` `        ``// previous visited index of string` `        ``if` `(s2.find(str[i]) != s2.end()) {` `            ``suffix[i] = suffix[i + 1];` `        ``}` `        ``else` `{`   `            ``// Else store value on next index + 1.` `            ``suffix[i] = suffix[i + 1] + 1;` `            ``s2.insert(str[i]);` `        ``}` `    ``}`   `    ``// Store the maximum sum` `    ``int` `maxi = -1;` `    ``for` `(``int` `i = 1; i < n; i++) {`   `        ``// Take sum of prefix[i-1] +` `        ``// suffix[i] so that the` `        ``// intersecting never counts.` `        ``maxi = max(maxi, prefix[i - 1] + suffix[i]);` `    ``}`   `    ``// Returning the maximum value` `    ``return` `maxi;` `}`   `// Driver code` `int` `main()` `{` `    ``string str = ``"abcabcd"``;`   `    ``// Size of the string` `    ``int` `n = str.length();`   `    ``// Function call` `    ``cout << ``"Maximum sum is "` `<< unique_charcters(str, n);` `    ``return` `0;` `}`

## Java

 `// Java code for above approach`   `import` `java.util.*;`   `class` `GFG {` `    ``public` `static` `void` `main(String[] args)` `    ``{` `        ``String str = ``"abcabcd"``;`   `        ``// Size of the string` `        ``int` `n = str.length();`   `        ``// Function call` `        ``System.out.println(``"Maximum sum is "` `                           ``+ (unique_characters(str, n)));` `    ``}`   `    ``public` `static` `int` `unique_characters(String str, ``int` `n)` `    ``{` `        ``// Declare set to check if the current` `        ``// character is previously` `        ``// appearing or not` `        ``TreeSet s1 = ``new` `TreeSet<>();` `        ``TreeSet s2 = ``new` `TreeSet<>();`   `        ``// Store the count of unique characters` `        ``// from starting index.` `        ``int``[] prefix = ``new` `int``[n];`   `        ``// Store the count of unique characters` `        ``// from last index.` `        ``int``[] suffix = ``new` `int``[n];` `        ``prefix[``0``] = ``1``;` `        ``suffix[n - ``1``] = ``1``;` `        ``s1.add(str.charAt(``0``));` `        ``s2.add(str.charAt(n - ``1``));`   `        ``// from starting index to last index` `        ``for` `(``int` `i = ``1``; i < n; i++) {`   `            ``// If the current character has` `            ``// appeared before, store` `            ``// previous value` `            ``if` `((s1.contains(str.charAt(i)))` `                ``&& str.charAt(i) != s1.last()) {` `                ``prefix[i] = prefix[i - ``1``];` `            ``}` `            ``else` `{` `                ``// else store previous value + 1.` `                ``prefix[i] = prefix[i - ``1``] + ``1``;` `                ``s1.add(str.charAt(i));` `            ``}` `        ``}`   `        ``// Storing the count of unique` `        ``// characters from last index` `        ``// to 0th index` `        ``for` `(``int` `i = n - ``2``; i >= ``0``; i--) {`   `            ``// If the current character has` `            ``// already appeared, store the` `            ``// value calculated for the` `            ``// previous visited index of string` `            ``if` `((s2.contains(str.charAt(i)))` `                ``&& str.charAt(i) != s2.last()) {` `                ``suffix[i] = suffix[i + ``1``];` `            ``}` `            ``else` `{` `                ``// Else store value on next index + 1.` `                ``suffix[i] = suffix[i + ``1``] + ``1``;` `                ``s2.add(str.charAt(i));` `            ``}` `        ``}`   `        ``// Store the maximum sum` `        ``int` `maxi = -``1``;` `        ``for` `(``int` `i = ``1``; i < n; i++) {`   `            ``// Take sum of prefix[i-1] +` `            ``// suffix[i] so that the` `            ``// intersecting never counts.` `            ``maxi` `                ``= Math.max(maxi, prefix[i - ``1``] + suffix[i]);` `        ``}`   `        ``// Returning the maximum value` `        ``return` `maxi;` `    ``}` `}`

## Python3

 `# Python code for the above approach:` `def` `unique_charcters(``str``, n):` `  ``# Declare set to check if the current` `  ``# character is previously` `  ``# appearing or not` `  ``s1 ``=` `set``()` `  ``s2 ``=` `set``()`   `  ``# Store the count of unique characters` `  ``# from starting index.` `  ``prefix ``=` `[``0``]``*``n`   `  ``# Store the count of unique characters` `  ``# from last index.` `  ``suffix ``=` `[``0``]``*``n`   `  ``prefix[``0``] ``=` `1` `  ``suffix[n ``-` `1``] ``=` `1` `  ``s1.add(``str``[``0``])` `  ``s2.add(``str``[n ``-` `1``])`   `  ``# Storing the count of unique characters` `  ``# from starting index to last index` `  ``for` `i ``in` `range``(``1``, n):`   `      ``# If the current character has` `      ``# appeared before, store` `      ``# previous value` `      ``if` `str``[i] ``in` `s1:` `          ``prefix[i] ``=` `prefix[i ``-` `1``]` `      ``else``:` `          ``# else store previous value + 1.` `          ``prefix[i] ``=` `prefix[i ``-` `1``] ``+` `1` `          ``s1.add(``str``[i])`   `  ``# Storing the count of unique` `  ``# characters from last index` `  ``# to 0th index` `  ``for` `i ``in` `range``(n``-``2``, ``-``1``, ``-``1``):`   `      ``# If the current character has` `      ``# already appeared, store the` `      ``# value calculated for the` `      ``# previous visited index of string` `      ``if` `str``[i] ``in` `s2:` `          ``suffix[i] ``=` `suffix[i ``+` `1``]` `      ``else``:`   `          ``# Else store value on next index + 1.` `          ``suffix[i] ``=` `suffix[i ``+` `1``] ``+` `1` `          ``s2.add(``str``[i])`   `  ``# Store the maximum sum` `  ``maxi ``=` `-``1` `  ``for` `i ``in` `range``(``1``, n):`   `      ``# Take sum of prefix[i-1] +` `      ``# suffix[i] so that the` `      ``# intersecting never counts.` `      ``maxi ``=` `max``(maxi, prefix[i ``-` `1``] ``+` `suffix[i])`   `  ``# Returning the maximum value` `  ``return` `maxi`   `if` `__name__ ``=``=` `"__main__"``:` `  ``str` `=` `"abcabcd"` `  ``# Size of the string` `  ``n ``=` `len``(``str``)`   `  ``# Function call` `  ``print``(``"Maximum sum is "``, unique_charcters(``str``, n))`

## C#

 `// C# code for above approach`   `using` `System;` `using` `System.Collections.Generic;`   `public` `class` `GFG {`   `    ``static` `int` `UniqueCharacters(``string` `str, ``int` `n)` `    ``{` `        ``// Declare set to check if the current character is` `        ``// previously appearing or not` `        ``SortedSet<``char``> s1 = ``new` `SortedSet<``char``>();` `        ``SortedSet<``char``> s2 = ``new` `SortedSet<``char``>();`   `        ``// Store the count of unique characters from` `        ``// starting index.` `        ``int``[] prefix = ``new` `int``[n];`   `        ``// Store the count of unique characters from last` `        ``// index.` `        ``int``[] suffix = ``new` `int``[n];` `        ``prefix = 1;` `        ``suffix[n - 1] = 1;` `        ``s1.Add(str);` `        ``s2.Add(str[n - 1]);`   `        ``// from starting index to last index` `        ``for` `(``int` `i = 1; i < n; i++) {` `            ``// If the current character has appeared before,` `            ``// store previous value` `            ``if` `((s1.Contains(str[i])) && str[i] != s1.Max) {` `                ``prefix[i] = prefix[i - 1];` `            ``}` `            ``else` `{` `                ``// else store previous value + 1.` `                ``prefix[i] = prefix[i - 1] + 1;` `                ``s1.Add(str[i]);` `            ``}` `        ``}`   `        ``// Storing the count of unique characters from last` `        ``// index to 0th index` `        ``for` `(``int` `i = n - 2; i >= 0; i--) {` `            ``// If the current character has already` `            ``// appeared, store the value calculated for the` `            ``// previous visited index of string` `            ``if` `((s2.Contains(str[i])) && str[i] != s2.Max) {` `                ``suffix[i] = suffix[i + 1];` `            ``}` `            ``else` `{` `                ``// Else store value on next index + 1.` `                ``suffix[i] = suffix[i + 1] + 1;` `                ``s2.Add(str[i]);` `            ``}` `        ``}`   `        ``// Store the maximum sum` `        ``int` `maxi = -1;` `        ``for` `(``int` `i = 1; i < n; i++) {` `            ``// Take sum of prefix[i-1] + suffix[i] so that` `            ``// the intersecting never counts.` `            ``maxi` `                ``= Math.Max(maxi, prefix[i - 1] + suffix[i]);` `        ``}`   `        ``// Returning the maximum value` `        ``return` `maxi;` `    ``}`   `    ``static` `public` `void` `Main()` `    ``{`   `        ``// Code` `        ``string` `str = ``"abcabcd"``;` `        ``// Size of the string` `        ``int` `n = str.Length;`   `        ``// Function call` `        ``Console.WriteLine(``"Maximum sum is "` `                          ``+ (UniqueCharacters(str, n)));` `    ``}` `}`   `// This code is contributed by sankar.`

## Javascript

 `// JavaScript code for the above approach:`   `// Function for finding out maximum value` `function` `uniqueCharacters(str, n) {`   `    ``// Declare set to check if the current` `    ``// character is previously` `    ``// appearing or not` `    ``var` `s1 = ``new` `Set();` `    ``var` `s2 = ``new` `Set();` `    `  `    ``// Store the count of unique characters` `    ``// from starting index.` `    ``var` `prefix = ``new` `Array(n);` `    `  `    ``// Store the count of unique characters` `    ``// from last index.` `    ``var` `suffix = ``new` `Array(n);` `    ``prefix = 1;` `    ``suffix[n - 1] = 1;` `    ``s1.add(str);` `    ``s2.add(str[n - 1]);` `    `  `    ``// Storing the count of unique characters` `    ``// from starting index to last index` `    ``for` `(``var` `i = 1; i < n; i++) {` `    `  `        ``// If the current character has` `        ``// appeared before, store` `        ``// previous value` `        ``if` `(s1.has(str[i])) {` `            ``prefix[i] = prefix[i - 1];` `        ``}` `        ``else` `{` `            ``// else store previous value + 1.` `            ``prefix[i] = prefix[i - 1] + 1;` `            ``s1.add(str[i]);` `        ``}` `    ``}` `    `  `    ``// Storing the count of unique` `    ``// characters from last index` `    ``// to 0th index` `    ``for` `(``var` `i = n - 2; i >= 0; i--) {` `    `  `        ``// If the current character has` `        ``// already appeared, store the` `        ``// value calculated for the` `        ``// previous visited index of string` `        ``if` `(s2.has(str[i])) {` `            ``suffix[i] = suffix[i + 1];` `        ``}` `        ``else` `{` `    `  `            ``// Else store value on next index + 1.` `            ``suffix[i] = suffix[i + 1] + 1;` `            ``s2.add(str[i]);` `        ``}` `    ``}` `    `  `    ``// Store the maximum sum` `    ``var` `maxi = -1;` `    ``for` `(``var` `i = 1; i < n; i++) {` `    `  `        ``// Take sum of prefix[i-1] +` `        ``// suffix[i] so that the` `        ``// intersecting never counts.` `        ``maxi = Math.max(maxi, prefix[i - 1] + suffix[i]);` `    ``}` `    `  `    ``// Returning the maximum value` `    ``return` `maxi;` `}`   `// Driver code` `var` `str = ``"abcabcd"``;`   `// Size of the string` `var` `n = str.length;`   `// Function call` `console.log(``"Maximum sum is "` `+ uniqueCharacters(str, n));`   `// This Code is Contributed by Prasad Kandekar(prasad264)`

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 ` `#include ` `#include `   `using` `namespace` `std;`   `int` `maxUniqueCharSubstring(string str, ``int` `N)` `{` `    ``// Initializing two frequency Hash Maps` `    ``unordered_map<``char``, ``int``> characters;` `    ``unordered_map<``char``, ``int``> freq;`   `    ``// Making a frequency map of characters` `    ``for` `(``int` `i = 0; i < N; i++) {` `        ``characters[str[i]]++;` `    ``}`   `    ``// max variable which contains maximum sum of unique` `    ``// characters` `    ``int` `max = INT_MIN;`   `    ``// Traversing the string` `    ``for` `(``int` `i = 0; i < N; i++) {` `        ``// Updating max variable` `        ``int` `totalChar = (characters.size() + freq.size());` `        ``if` `(max < totalChar) {` `            ``max = totalChar;` `        ``}` `        ``// Updating both hash maps` `        ``freq[str[i]]++;` `        ``characters[str[i]]--;`   `        ``if` `(characters[str[i]] == 0) {` `            ``characters.erase(str[i]);` `        ``}` `    ``}`   `    ``// Returning max value` `    ``return` `max;` `}`   `int` `main()` `{` `    ``string str = ``"abcabcd"``;` `    ``int` `N = str.length();` `    ``cout << ``"Maximum sum is "` `         ``<< maxUniqueCharSubstring(str, N) << endl;` `    ``return` `0;` `}`

## Java

 `// Java algorithm for the above approach`   `import` `java.util.*;`   `class` `GFG {` `    ``// Driver Code` `    ``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)` `    ``{` `        ``// Initializing two frequency Hash Maps` `        ``Map characters` `            ``= ``new` `HashMap<>();` `        ``Map freq = ``new` `HashMap<>();`   `        ``// Making a frequency map of characters` `        ``for` `(``int` `i = ``0``; i < N; i++) {` `            ``characters.put(` `                ``str.charAt(i),` `                ``characters.getOrDefault(str.charAt(i), ``0``)` `                    ``+ ``1``);` `        ``}` `        ``// max variable which contains maximum sum of unique` `        ``// characters` `        ``int` `max = Integer.MIN_VALUE;` `        ``// Traversing the string` `        ``for` `(``int` `i = ``0``; i < N; i++) {` `            ``// Updating max variable` `            ``if` `(max < characters.size() + freq.size()) {` `                ``max = characters.size() + freq.size();` `            ``}` `            ``// Updating both hash maps` `            ``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));` `        ``}` `        ``// Returning max value` `        ``return` `max;` `    ``}` `}`

## Python3

 `# Python code for the above approach` `def` `maxUniqueCharSubstring(string):` `    ``# Initializing two frequency dictionaries` `    ``characters ``=` `{}` `    ``freq ``=` `{}`   `    ``# Making a frequency map of characters` `    ``for` `i ``in` `string:` `        ``if` `i ``in` `characters:` `            ``characters[i] ``+``=` `1` `        ``else``:` `            ``characters[i] ``=` `1`   `    ``# max variable which contains maximum sum of unique` `    ``# characters` `    ``max_len ``=` `float``(``'-inf'``)`   `    ``# Traversing the string` `    ``for` `i ``in` `range``(``len``(string)):` `        ``# Updating max variable` `        ``if` `max_len < ``len``(characters) ``+` `len``(freq):` `            ``max_len ``=` `len``(characters) ``+` `len``(freq)`   `        ``# Updating both dictionaries` `        ``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]]`   `    ``# Returning max value` `    ``return` `max_len`     `# Driver code` `string ``=` `"abcabcd"` `print``(``"Maximum sum is"``, maxUniqueCharSubstring(string))` `# This code is contributed by codearcade.`

## C#

 `// C# code for the above approach`   `using` `System;` `using` `System.Collections.Generic;`   `public` `class` `GFG {`   `    ``public` `static` `int` `maxUniqueCharSubstring(``string` `str,` `                                             ``int` `N)` `    ``{` `        ``// Initializing two frequency Hash Maps` `        ``Dictionary<``char``, ``int``> characters` `            ``= ``new` `Dictionary<``char``, ``int``>();` `        ``Dictionary<``char``, ``int``> freq` `            ``= ``new` `Dictionary<``char``, ``int``>();`   `        ``// Making a frequency map of characters` `        ``for` `(``int` `i = 0; i < N; i++) {` `            ``if` `(characters.ContainsKey(str[i]))` `                ``characters[str[i]] += 1;` `            ``else` `                ``characters.Add(str[i], 1);` `        ``}`   `        ``// max variable which contains maximum sum of unique` `        ``// characters` `        ``int` `max = ``int``.MinValue;`   `        ``// Traversing the string` `        ``for` `(``int` `i = 0; i < N; i++) {` `            ``// Updating max variable` `            ``if` `(max < characters.Count + freq.Count) {` `                ``max = characters.Count + freq.Count;` `            ``}`   `            ``// Updating both hash maps` `            ``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]);` `        ``}`   `        ``// Returning max value` `        ``return` `max;` `    ``}`   `    ``static` `public` `void` `Main()` `    ``{`   `        ``// Code` `        ``string` `str = ``"abcabcd"``;` `        ``int` `N = str.Length;` `        ``Console.WriteLine(``"Maximum sum is "` `                          ``+ maxUniqueCharSubstring(str, N));` `    ``}` `}`   `// This code is contributed by karthik.`

## Javascript

 `// JavaScript code for the above approach` `function` `maxUniqueCharSubstring(str, N)` `{`   `    ``// Initializing two frequency Hash Maps` `    ``let characters = ``new` `Map();` `    ``let freq = ``new` `Map();`   `    ``// Making a frequency map of characters` `    ``for` `(let i = 0; i < N; i++) {` `        ``characters.set(str[i], (characters.get(str[i]) || 0) + 1);` `    ``}`   `    ``// max variable which contains maximum sum of unique` `    ``// characters` `    ``let max = Number.MIN_SAFE_INTEGER;`   `    ``// Traversing the string` `    ``for` `(let i = 0; i < N; i++) {` `        ``// Updating max variable` `        ``let totalChar = (characters.size + freq.size);` `        ``if` `(max < totalChar) {` `            ``max = totalChar;` `        ``}`   `        ``// Updating both hash maps` `        ``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]);` `        ``}` `    ``}`   `    ``// Returning max value` `    ``return` `max;` `}`   `let str = ``"abcabcd"``;` `let N = str.length;` `console.log(``"Maximum sum is "` `+ maxUniqueCharSubstring(str, N));`   `// This code is contributed by prasad264`

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.

My Personal Notes arrow_drop_up
Related Articles