Split a string in equal parts such that all parts are palindromes

Given a string str, the task is to split the string into minimum parts such that each part is of same length and each part is a palindrome. Print the required number of parts.

Examples:

Input: str = “civicbob”
Output: 8
“b”, “b”, “c”, “c”, “i”, “i”, “v” and “o” are the required partitions. “civic” and “bob” are also palindromes but they are not of equal length

Input: str = “noonpeep”
Output: 1

Approach:

  • Count the number of odd appearing characters and store it in countOdd.
  • Sum the frequencies of all the even occurring characters and store it in sumEven.
  • Since, no more than one odd frequency character can be a part of the same palindrome. So, if (sumEven / 2) % countOdd = 0 then the answer is countOdd as sumEven can be divided into countOdd parts.
  • Else, we can still divide the odd occurring characters into the palindrome pairs. For example, if the character a appears 3 times i.e. aaa then aa can be a part of some palindrome while leaving a as odd (without affecting the original frequency).

Below is the implementation of the above approach:

Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java implementation of the approach
import java.util.*;
public class GFG {
  
    // Function to return the frequency array
    // for the given string
    static int[] getFrequencies(String str)
    {
        int freq[] = new int[26];
        for (int i = 0; i < str.length(); i++) {
            freq[str.charAt(i) - 'a']++;
        }
        return freq;
    }
  
    // Function to return the required count
    static int countMinParts(String str)
    {
  
        int n = str.length();
        int freq[] = getFrequencies(str);
        List<Integer> oddFreq = new ArrayList<>();
        List<Integer> evenFreq = new ArrayList<>();
  
        int i, sumEven = 0;
  
        for (i = 0; i < 26; i++) {
            if (freq[i] == 0)
                continue;
  
            // Add frequencies of the even appearing 
            // characters
            if (freq[i] % 2 == 0)
                evenFreq.add(freq[i]);
  
            // Count of the characters that appeared 
            // odd number of times
            else
                oddFreq.add(freq[i]);
        }
  
        for (i = 0; i < evenFreq.size(); i++) {
            sumEven += evenFreq.get(i);
        }
  
        // If there are no characters with odd frequency
        if (oddFreq.size() == 0)
            return 1;
  
        // If there are no characters with even frequency
        if (sumEven == 0) {
  
            // Only a single character with odd frequency
            if (oddFreq.size() == 1)
                return 1;
  
            // More than 1 character with odd frequency
            // string isn't a palindrome
            return 0;
        }
  
        i = 0;
  
        // All odd appearing characters can also contribute to
        // the even length palindrome if one character
        // is removed from the frequency leaving it as even
        while (i < oddFreq.size()) {
  
            // If k palindromes are possible where k
            // is the number of characters with odd frequency
            if ((sumEven / 2) % oddFreq.size() == 0)
                return oddFreq.size();
  
            // Current character can no longer be an element
            // in a string other than the mid character
            if (oddFreq.get(i) == 1) {
                i++;
                continue;
            }
  
            // If current character has odd frequency > 1
            // take two characters which can be used in
            // any of the parts
            sumEven += 2;
  
            // Update the frequency
            oddFreq.set(i, oddFreq.get(i) - 2);
        }
  
        // If not possible, then every character of the 
        // string will act as a separate palindrome
        return n;
    }
  
    // Driver code
    public static void main(String[] args)
    {
  
        String s = "noonpeep";
  
        System.out.println(countMinParts(s));
    }
}

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 implementation of the approach 
  
# Function to return the frequency array 
# for the given string 
def getFrequencies(string) :
        freq = [0] * 26
  
        for i in range(len(string)) :
                freq[ord(string[i]) - 
                     ord('a')] += 1
  
        return freq
  
# Function to return the required count 
def countMinParts(string) :
        n = len(string)
        freq = getFrequencies(string)
        oddFreq = []
        evenFreq = []
  
        sumEven = 0
  
        for i in range(26) :
  
                if freq[i] == 0 :
                    continue
  
                # Add frequencies of the even 
                # appearing characters 
                if freq[i] % 2 == 0 :
                        evenFreq.append(freq[i])
  
                # Count of the characters that 
                # appeared odd number of times
                else :
                        oddFreq.append(freq[i])
  
        for i in range(len(evenFreq)) :
                sumEven += evenFreq[i]
  
        # If there are no characters with
        # odd frequency 
        if len(oddFreq) == 0 :
                return 1
  
        # If there are no characters with 
        # even frequency
        if sumEven == 0 :
  
                # Only a single character with
                # odd frequency
                if len(oddFreq) == 1:
                        return 1
  
                # More than 1 character with odd 
                # frequency string isn't a palindrome 
                return 0
  
        i = 0
  
        # All odd appearing characters can also 
        # contribute to the even length palindrome 
        # if one character is removed from the 
        # frequency leaving it as even
        while(i < len(oddFreq)) :
                  
                # If k palindromes are possible where 
                # k is the number of characters with 
                # odd frequency 
                if ((sumEven / 2) % len(oddFreq) == 0) :
                        return len(oddFreq)
  
                # Current character can no longer be 
                # an element in a string other than
                # the mid character 
                if (oddFreq[i] == 1) :
                        i += 1
                        continue
  
                # If current character has odd frequency > 1 
                # take two characters which can be used in 
                # any of the parts 
                sumEven += 2
  
                # Update the frequency
                oddFreq[i] = oddFreq[i] - 2
  
        # If not possible, then every character of the 
        # string will act as a separate palindrome 
        return n
  
# Driver code
if __name__ == "__main__" :
  
    s = "noonpeep"
  
    print(countMinParts(s))
  
# This code is contributed by Ryuga

chevron_right


Output:

1


My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.



Improved By : Ryuga