Open In App

String Partitioning for Character Equality

Last Updated : 28 Nov, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given a string S of size N, the task is to divide the given string into two non-empty strings s1 and s2 such that the number of distinct characters in s1 is equal to s2.

Examples:

Input: s = “aacaba”
Output: 2
Explanation:
=> Dividing s into s1 and s2 as (“aac”, “aba”), the left string contains 2 distinct letters, and the right string also contains 2 distinct letters.
=> Dividing s into s1 and s2 as (“aaca”, “ba”), where the left and right strings both contain 2 distinct letters.

Input: s = “abcd”
Output: 1

String Partitioning for Character Equality using Hashing:

Maintain two unordered maps to keep track of character counts for the left (s1) and right(s2) portions of the string. As it iterates through the string, updates the maps and checks if the counts of distinct characters in both sides match, incrementing a count for each valid division. The final count represents the number of such valid division in the string.

Step-by-step approach:

  • Initialize counts and maps for left (s1) and right (s2) portions of the string.
  • Iterate through the string.
    • Update the maps and counts accordingly.
    • Check if the counts of distinct characters on both sides are equal.
    • Increment a count for valid division.
  • Return the count as the result.

Below is the implementation of the above approach:

C++




#include <bits/stdc++.h>
using namespace std;
 
int divideString(string& s)
{
    int n = s.size();
 
    if (n == 1) {
        return 0;
    }
 
    // Create two unordered maps to store character counts
    // for the left and right portions of the string.
    unordered_map<char, int> rightMap, leftMap;
 
    for (char c : s) {
        rightMap++;
    }
 
    // Initialize a count to track the number of valid
    // division.
    int count = 0;
 
    // Iterate through the string.
    for (int i = 0; i < n - 1; i++) {
        // Update the leftMap with the character at the
        // current position.
        leftMap[s[i]]++;
 
        // Update the rightMap by decreasing the count of
        // the same character.
        rightMap[s[i]]--;
 
        // If there are no more occurrences of the character
        // in the rightMap, remove it to keep the maps
        // compact.
        if (rightMap[s[i]] == 0) {
            rightMap.erase(s[i]);
        }
 
        // Check if the number of distinct characters in the
        // leftMap is equal to the number of distinct
        // characters in the rightMap.
        if (leftMap.size() == rightMap.size()) {
            count++;
        }
    }
 
    // Return the total count of valid
    // division.
    return count;
}
 
// Drivers code
int main()
{
 
    string s = "aacaba";
 
    int result = divideString(s);
 
    // Function Call
    cout << result << endl;
 
    return 0;
}


Java




/*contributed by flutterfly*/
import java.util.HashMap;
import java.util.Map;
 
public class DivideString {
 
    static int divideString(String s) {
        int n = s.length();
 
        if (n == 1) {
            return 0;
        }
 
        // Create two hash maps to store character counts
        // for the left and right portions of the string.
        Map<Character, Integer> rightMap = new HashMap<>();
        Map<Character, Integer> leftMap = new HashMap<>();
        // Initialize a count to track the number of valid
        // division.
        int count = 0;
        // Iterate through the string
        for (char c : s.toCharArray()) {
            rightMap.put(c, rightMap.getOrDefault(c, 0) + 1);
        }
        // Update the leftMap with the character at the
        // current position.
        for (int i = 0; i < n - 1; i++) {
            leftMap.put(s.charAt(i), leftMap.getOrDefault(s.charAt(i), 0) + 1);
              // If there are no more occurrences of the character
            // in the rightMap, remove it to keep the maps
            // compact.
            rightMap.put(s.charAt(i), rightMap.get(s.charAt(i)) - 1);
            // If there are no more occurrences of the character
            // in the rightMap, remove it to keep the maps
            // compact.
            if (rightMap.get(s.charAt(i)) == 0) {
                rightMap.remove(s.charAt(i));
            }                 
              // Check if the number of distinct characters in the
            // leftMap is equal to the number of distinct
            // characters in the rightMap.
            if (leftMap.size() == rightMap.size()) {
                count++;
            }
        }
        // Return the total count of valid
        // division.
        return count;
    }
//Driver's code
    public static void main(String[] args) {
        String s = "aacaba";
          // Function Call
        int result = divideString(s);
        System.out.println(result);
    }
}


Python




# code by flutterfly
def divide_string(s):
    n = len(s)
 
    if n == 1:
        return 0
 
    # Create two dictionaries to store character counts
    # for the left and right portions of the string.
    right_map, left_map = {}, {}
    #Initialize a count to track the number of valid
    # division.
    count = 0
    #// Iterate through the string.
    for c in s:
        right_map = right_map.get(c, 0) + 1
 
    for i in range(n - 1):
          #Update the leftMap with the character at the
        #current position
        left_map[s[i]] = left_map.get(s[i], 0) + 1
        #Update the rightMap by decreasing the count of
        #the same character.
        right_map[s[i]] -= 1
        # If there are no more occurrences of the character
        # in the rightMap, remove it to keep the maps
        # compact.
        if right_map[s[i]] == 0:
            del right_map[s[i]]
        #Check if the number of distinct characters in the
        # leftMap is equal to the number of distinct
        # characters in the rightMap.
        if len(left_map) == len(right_map):
            count += 1
        #Return the total count of valid
        # division.
    return count
 
# Driver code
s = "aacaba"
#Function's Call
result = divide_string(s)
print(result)


C#




// code by flutterfly
using System;
using System.Collections.Generic;
 
class Program
{
    static int DivideString(string s)
    {
        int n = s.Length;
 
        if (n == 1)
        {
            return 0;
        }
 
        // Create two dictionaries to store character counts
        // for the left and right portions of the string.
        Dictionary<char, int> rightMap = new Dictionary<char, int>();
        Dictionary<char, int> leftMap = new Dictionary<char, int>();
        // Initialize a count to track the number of valid
        // division.
        int count = 0;
        // Iterate through the string.
        foreach (char c in s)
        {
            rightMap = rightMap.GetValueOrDefault(c, 0) + 1;
        }
 
        for (int i = 0; i < n - 1; i++)
        {
              // Update the leftMap with the character at the
            // current position.
            leftMap[s[i]] = leftMap.GetValueOrDefault(s[i], 0) + 1;
              // Update the rightMap by decreasing the count of
            // the same character.
            rightMap[s[i]]--;
            // If there are no more occurrences of the character
            // in the rightMap, remove it to keep the maps
            // compact.
            if (rightMap[s[i]] == 0)
            {
                rightMap.Remove(s[i]);
            }
            // Check if the number of distinct characters in the
            // leftMap is equal to the number of distinct
            // characters in the rightMap.
            if (leftMap.Count == rightMap.Count)
            {
                count++;
            }
        }
        // Return the total count of valid
        // division.
        return count;
    }
//Driver's code
    static void Main()
    {
        string s = "aacaba";
          // Function Call
        int result = DivideString(s);
        Console.WriteLine(result);
    }
}


Javascript




function divideString(s) {
    const n = s.length;
 
    if (n === 1) {
        return 0;
    }
 
    // Create two objects to store character counts
    // for the left and right portions of the string.
    const rightMap = {};
    const leftMap = {};
    // Initialize a count to track the number of valid
    // division.
    let count = 0;
    // Iterate through the string.
    for (const c of s) {
        rightMap = (rightMap || 0) + 1;
    }
    // Update the leftMap with the character at the
    // current position.
    for (let i = 0; i < n - 1; i++) {
        leftMap[s[i]] = (leftMap[s[i]] || 0) + 1;
        // Update the rightMap by decreasing the count of
        // the same character.
        rightMap[s[i]]--;
        // If there are no more occurrences of the character
        // in the rightMap, remove it to keep the maps
        // compact.
        if (rightMap[s[i]] === 0) {
            delete rightMap[s[i]];
        }
        // Check if the number of distinct characters in the
        // leftMap is equal to the number of distinct
        // characters in the rightMap.
        if (Object.keys(leftMap).length === Object.keys(rightMap).length) {
            count++;
        }
    }
    // Return the total count of valid
    // division.
    return count;
}
 
// Driver code
const s = "aacaba";
//Function's Call
const result = divideString(s);
console.log(result);


Output

2

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



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads