Open In App

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

Improve
Improve
Like Article
Like
Save
Share
Report

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:
“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:

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: 

C++




// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to return the frequency array
// for the given string
int* getFrequencies(string str)
{
    static int freq[26] = { 0 };
 
    for (int i = 0; i < str.length(); i++) {
        freq[str[i] - 'a']++;
    }
 
    return freq;
}
 
// Function to return the required count
int countMinParts(string str)
{
 
    int n = str.length();
    int *freq = getFrequencies(str);
 
    vector<int> oddFreq, evenFreq;
 
    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.push_back(freq[i]);
 
        // Count of the characters that appeared
        // odd number of times
        else
            oddFreq.push_back(freq[i]);
    }
 
    for (i = 0; i < evenFreq.size(); i++) {
        sumEven += evenFreq[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[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[i] = oddFreq[i] - 2;
    }
 
    // If not possible, then every character of the
    // string will act as a separate palindrome
    return n;
}
 
// Driver code
int main()
{
 
    string s = "noonpeep";
 
    cout<<countMinParts(s);
}


Java




// 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));
    }
}
 
// This code is contributed by chitranayal


Python3




# 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


C#




// C# implementation of the approach
using System;
using System.Collections.Generic;
 
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[i] - 'a']++;
        }
        return freq;
    }
 
    // Function to return the required count
    static int countMinParts(String str)
    {
 
        int n = str.Length;
        int []freq = getFrequencies(str);
        List<int> oddFreq = new List<int>();
        List<int> evenFreq = new List<int>();
 
        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.Count; i++)
        {
            sumEven += evenFreq[i];
        }
 
        // If there are no characters with odd frequency
        if (oddFreq.Count == 0)
            return 1;
 
        // If there are no characters with even frequency
        if (sumEven == 0)
        {
 
            // Only a single character with odd frequency
            if (oddFreq.Count == 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.Count)
        {
 
            // If k palindromes are possible where k
            // is the number of characters with odd frequency
            if ((sumEven / 2) % oddFreq.Count == 0)
                return oddFreq.Count;
 
            // Current character can no longer be an element
            // in a string other than the mid character
            if (oddFreq[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.Insert(i, oddFreq[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";
 
        Console.WriteLine(countMinParts(s));
    }
}
 
// This code has been contributed by 29AjayKumar


Javascript




<script>
 
// Javascript implementation of the approach
 
// Function to return the frequency array
    // for the given string
function getFrequencies(str)
{
    let freq = new Array(26);
    for(let i=0;i<26;i++)
        freq[i]=0;
        for (let i = 0; i < str.length; i++) {
            freq[str[i].charCodeAt(0) - 'a'.charCodeAt(0)]++;
        }
        return freq;
}
 
// Function to return the required count
function countMinParts(str)
{
        let n = str.length;
        let freq = getFrequencies(str);
        let oddFreq = [];
        let evenFreq = [];
   
        let 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.push(freq[i]);
   
            // Count of the characters that appeared
            // odd number of times
            else
                oddFreq.push(freq[i]);
        }
   
        for (i = 0; i < evenFreq.length; i++) {
            sumEven += evenFreq[i];
        }
   
        // If there are no characters with odd frequency
        if (oddFreq.length == 0)
            return 1;
   
        // If there are no characters with even frequency
        if (sumEven == 0) {
   
            // Only a single character with odd frequency
            if (oddFreq.length == 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.length) {
   
            // If k palindromes are possible where k
            // is the number of characters with odd frequency
            if ((sumEven / 2) % oddFreq.length == 0)
                return oddFreq.length;
   
            // Current character can no longer be an element
            // in a string other than the mid character
            if (oddFreq[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[i]= oddFreq[i] - 2;
        }
   
        // If not possible, then every character of the
        // string will act as a separate palindrome
        return n;
}
 
 // Driver code
let s = "noonpeep";
 
document.write(countMinParts(s));
 
// This code is contributed by rag2127
 
</script>


Output

1

Time complexity: O(n) where n is the length of the given string
Auxiliary space: O(1)



Last Updated : 19 Oct, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads