Skip to content
Related Articles

Related Articles

Palindrome Partitioning | DP-17
  • Difficulty Level : Hard
  • Last Updated : 31 Mar, 2021

Given a string, a partitioning of the string is a palindrome partitioning if every substring of the partition is a palindrome. For example, “aba|b|bbabb|a|b|aba” is a palindrome partitioning of “ababbbabbababa”. Determine the fewest cuts needed for a palindrome partitioning of a given string. For example, minimum of 3 cuts are needed for “ababbbabbababa”. The three cuts are “a|babbbab|b|ababa”. If a string is a palindrome, then minimum 0 cuts are needed. If a string of length n containing all different characters, then minimum n-1 cuts are needed. 

palindrome-partitioning

Examples :  

Input : str = “geek” 
Output : 2 
We need to make minimum 2 cuts, i.e., “g ee k”
Input : str = “aaaa” 
Output : 0 
The string is already a palindrome.
Input : str = “abcde” 
Output : 4
Input : str = “abbac” 
Output : 1 
 

This problem is a variation of Matrix Chain Multiplication problem. If the string is a palindrome, then we simply return 0. Else, like the Matrix Chain Multiplication problem, we try making cuts at all possible places, recursively calculate the cost for each cut and return the minimum value. 
Let the given string be str and minPalPartion() be the function that returns the fewest cuts needed for palindrome partitioning. following is the optimal substructure property.



Using Recursion 

// i is the starting index and j is the ending index. i must be passed as 0 and j as n-1
minPalPartion(str, i, j) = 0 if i == j. // When string is of length 1.
minPalPartion(str, i, j) = 0 if str[i..j] is palindrome.

// If none of the above conditions is true, then minPalPartion(str, i, j) can be 
// calculated recursively using the following formula.
minPalPartion(str, i, j) = Min { minPalPartion(str, i, k) + 1 +
                                 minPalPartion(str, k+1, j) } 
                           where k varies from i to j-1

C++




// C++ Code for Palindrome Partitioning
// Problem
#include <bits/stdc++.h>
using namespace std;
 
bool isPalindrome(string String, int i, int j)
{
    while(i < j)
    {
      if(String[i] != String[j])
        return false
      i++;
      j--;
    }
    return true;
}
int minPalPartion(string String, int i, int j)
{
    if( i >= j || isPalindrome(String, i, j) )
      return 0;
    int ans = INT_MAX, count;
    for(int k = i; k < j; k++)
    {
      count = minPalPartion(String, i, k) +
        minPalPartion(String, k + 1, j) + 1;
  
      ans = min(ans, count);
    }
    return ans;
}
 
// Driver code
int main() {
    string str = "ababbbabbababa";
    cout << "Min cuts needed for " <<
      "Palindrome Partitioning is " << 
      minPalPartion(str, 0, str.length() - 1) << endl;
    return 0;
}
 
// This code is contributed by rag2127

Java




// Java Code for Palindrome Partitioning
// Problem
public class GFG
{
 
  static boolean isPalindrome(String string, int i, int j)
  {
    while(i < j)
    {
      if(string.charAt(i) != string.charAt(j))
        return false
      i++;
      j--;
    }
    return true;
  }
 
  static int minPalPartion(String string, int i, int j)
  {   
    if( i >= j || isPalindrome(string, i, j) )
      return 0;
    int ans = Integer.MAX_VALUE, count;
    for(int k = i; k < j; k++)
    {
      count = minPalPartion(string, i, k) +
        minPalPartion(string, k + 1, j) + 1;
 
      ans = Math.min(ans, count);
    }
    return ans;
  }
 
  // Driver code
  public static void main(String args[])
  {
    String str = "ababbbabbababa";
    System.out.println("Min cuts needed for "
                       + "Palindrome Partitioning is " + minPalPartion(str, 0, str.length() - 1));
  }
}
 
// This code is contributed by adityapande88.

Python3




# Python code for implementation of Naive Recursive
# approach
def isPalindrome(x):
    return x == x[::-1]
 
 
def minPalPartion(string, i, j):
    if i >= j or isPalindrome(string[i:j + 1]):
        return 0
    ans = float('inf')
    for k in range(i, j):
        count = (
            1 + minPalPartion(string, i, k)
            + minPalPartion(string, k + 1, j)
        )
        ans = min(ans, count)
    return ans
 
 
def main():
    string = "ababbbabbababa"
     print(
     "Min cuts needed for Palindrome Partitioning is ",
     minPalPartion(string, 0, len(string) - 1),
    )
 
if __name__ == "__main__":
    main()
 
# This code is contributed by itsvinayak

C#




// C# Code for Palindrome Partitioning
// Problem
using System;
public class GFG
{
 
  static bool isPalindrome(string String, int i, int j)
  {
    while(i < j)
    {
      if(String[i] != String[j])
        return false
      i++;
      j--;
    }
    return true;
  }
 
  static int minPalPartion(string String, int i, int j)
  {   
    if( i >= j || isPalindrome(String, i, j) )
      return 0;
    int ans = Int32.MaxValue, count;
    for(int k = i; k < j; k++)
    {
      count = minPalPartion(String, i, k) +
        minPalPartion(String, k + 1, j) + 1;
 
      ans = Math.Min(ans, count);
    }
    return ans;
  }
 
  // Driver code
  static public void Main (){
    string str = "ababbbabbababa";
    Console.WriteLine("Min cuts needed for "+
                      "Palindrome Partitioning is " +
                      minPalPartion(str, 0, str.Length - 1));
  }
}
 
// This code is contributed by avanitrachhadiya2155

Javascript




<script>
 
// Javascript code for Palindrome
// Partitioning Problem
function isPalindrome(String, i, j)
{
    while (i < j)
    {
        if (String[i] != String[j])
            return false;
             
        i++;
        j--;
    }
    return true;
}
 
function minPalPartion(String, i, j)
{
    if (i >= j || isPalindrome(String, i, j))
        return 0;
         
    let ans = Number.MAX_VALUE, count;
     
    for(let k = i; k < j; k++)
    {
        count = minPalPartion(String, i, k) +
        minPalPartion(String, k + 1, j) + 1;
        ans = Math.min(ans, count);
    }
    return ans;
}
 
// Driver code
let str = "ababbbabbababa";
document.write("Min cuts needed for " +
               "Palindrome Partitioning is " +
               minPalPartion(str, 0, str.length - 1));
   
// This code is contributed by suresh07
 
</script>

Output: 

Min cuts needed for Palindrome Partitioning is 3 

Using Dynamic Programming
Following is Dynamic Programming solution. It stores the solutions to subproblems in two arrays P[][] and C[][], and reuses the calculated values. 

C++




// Dynamic Programming Solution for
// Palindrome Partitioning Problem
#include <bits/stdc++.h>
using namespace std;
 
// Returns the minimum number of cuts
// needed to partition a string
// such that every part is a palindrome
int minPalPartion(string str)
{
    // Get the length of the string
    int n = str.length();
 
    /* Create two arrays to build the solution
       in bottom up manner
    C[i][j] = Minimum number of cuts needed for
              palindrome partitioning
              of substring str[i..j]
    P[i][j] = true if substring str[i..j] is
              palindrome, else false
    Note that C[i][j] is 0 if P[i][j] is true */
    int C[n][n];
    bool P[n][n];
 
    // Every substring of length 1 is a palindrome
    for (int i = 0; i < n; i++) {
        P[i][i] = true;
        C[i][i] = 0;
    }
 
    /* L is substring length. Build the
    solution in bottom up manner by
    considering all substrings of
    length starting from 2 to n.
    The loop structure is same as Matrx
    Chain Multiplication problem
    ( See https:// www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/ )*/
    for (int L = 2; L <= n; L++) {
 
        // For substring of length L, set
        // different possible starting indexes
        for (int i = 0; i < n - L + 1; i++) {
            int j = i + L - 1; // Set ending index
 
            // If L is 2, then we just need to
            // compare two characters. Else
            // need to check two corner characters
            // and value of P[i+1][j-1]
            if (L == 2)
                P[i][j] = (str[i] == str[j]);
            else
                P[i][j] = (str[i] == str[j]) && P[i + 1][j - 1];
 
            // IF str[i..j] is palindrome, then C[i][j] is 0
            if (P[i][j] == true)
                C[i][j] = 0;
            else {
 
                // Make a cut at every possible
                // location starting from i to j,
                // and get the minimum cost cut.
                C[i][j] = INT_MAX;
                for (int k = i; k <= j - 1; k++)
                    C[i][j] = min(C[i][j], C[i][k] + C[k + 1][j] + 1);
            }
        }
    }
 
    // Return the min cut value for
    // complete string. i.e., str[0..n-1]
    return C[0][n - 1];
}
 
// Driver code
int main()
{
    string str = "ababbbabbababa";
    cout << "Min cuts needed for Palindrome"
            " Partitioning is "
         << minPalPartion(str);
    return 0;
}
 
// This code is contributed by rathbhupendra

C




// Dynamic Programming Solution for Palindrome Partitioning Problem
#include <limits.h>
#include <stdio.h>
#include <string.h>
 
// A utility function to get minimum of two integers
int min(int a, int b) { return (a < b) ? a : b; }
 
// Returns the minimum number of cuts needed to partition a string
// such that every part is a palindrome
int minPalPartion(char* str)
{
    // Get the length of the string
    int n = strlen(str);
 
    /* Create two arrays to build the solution in bottom up manner
       C[i][j] = Minimum number of cuts needed for palindrome partitioning
                 of substring str[i..j]
       P[i][j] = true if substring str[i..j] is palindrome, else false
       Note that C[i][j] is 0 if P[i][j] is true */
    int C[n][n];
    bool P[n][n];
 
    int i, j, k, L; // different looping variables
 
    // Every substring of length 1 is a palindrome
    for (i = 0; i < n; i++) {
        P[i][i] = true;
        C[i][i] = 0;
    }
 
    /* L is substring length. Build the solution in bottom up manner by
       considering all substrings of length starting from 2 to n.
       The loop structure is same as Matrx Chain Multiplication problem (
       See https:// www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/ )*/
    for (L = 2; L <= n; L++) {
        // For substring of length L, set different possible starting indexes
        for (i = 0; i < n - L + 1; i++) {
            j = i + L - 1; // Set ending index
 
            // If L is 2, then we just need to compare two characters. Else
            // need to check two corner characters and value of P[i+1][j-1]
            if (L == 2)
                P[i][j] = (str[i] == str[j]);
            else
                P[i][j] = (str[i] == str[j]) && P[i + 1][j - 1];
 
            // IF str[i..j] is palindrome, then C[i][j] is 0
            if (P[i][j] == true)
                C[i][j] = 0;
            else {
 
                // Make a cut at every possible location starting from i to j,
                // and get the minimum cost cut.
                C[i][j] = INT_MAX;
                for (k = i; k <= j - 1; k++)
                    C[i][j] = min(C[i][j], C[i][k] + C[k + 1][j] + 1);
            }
        }
    }
 
    // Return the min cut value for complete string. i.e., str[0..n-1]
    return C[0][n - 1];
}
 
// Driver program to test above function
int main()
{
    char str[] = "ababbbabbababa";
    printf("Min cuts needed for Palindrome Partitioning is %d",
           minPalPartion(str));
    return 0;
}

Java




// Java Code for Palindrome Partitioning
// Problem
public class GFG {
    // Returns the minimum number of cuts needed
    // to partition a string such that every
    // part is a palindrome
    static int minPalPartion(String str)
    {
        // Get the length of the string
        int n = str.length();
 
        /* Create two arrays to build the solution
           in bottom up manner
           C[i][j] = Minimum number of cuts needed
                     for palindrome partitioning
                     of substring str[i..j]
           P[i][j] = true if substring str[i..j] is
                     palindrome, else false
           Note that C[i][j] is 0 if P[i][j] is
           true */
        int[][] C = new int[n][n];
        boolean[][] P = new boolean[n][n];
 
        int i, j, k, L; // different looping variables
 
        // Every substring of length 1 is a palindrome
        for (i = 0; i < n; i++) {
            P[i][i] = true;
            C[i][i] = 0;
        }
 
        /* L is substring length. Build the solution in
         bottom up manner by considering all substrings
         of length starting from 2 to n. The loop
         structure is same as Matrx Chain Multiplication
         problem (
        See https:// www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/ )*/
        for (L = 2; L <= n; L++) {
            // For substring of length L, set different
            // possible starting indexes
            for (i = 0; i < n - L + 1; i++) {
                j = i + L - 1; // Set ending index
 
                // If L is 2, then we just need to
                // compare two characters. Else need to
                // check two corner characters and value
                // of P[i+1][j-1]
                if (L == 2)
                    P[i][j] = (str.charAt(i) == str.charAt(j));
                else
                    P[i][j] = (str.charAt(i) == str.charAt(j)) && P[i + 1][j - 1];
 
                // IF str[i..j] is palindrome, then
                // C[i][j] is 0
                if (P[i][j] == true)
                    C[i][j] = 0;
                else {
                    // Make a cut at every possible
                    // localtion starting from i to j,
                    // and get the minimum cost cut.
                    C[i][j] = Integer.MAX_VALUE;
                    for (k = i; k <= j - 1; k++)
                        C[i][j] = Integer.min(C[i][j],
                                              C[i][k] + C[k + 1][j] + 1);
                }
            }
        }
 
        // Return the min cut value for complete
        // string. i.e., str[0..n-1]
        return C[0][n - 1];
    }
 
    // Driver program to test above function
    public static void main(String args[])
    {
        String str = "ababbbabbababa";
        System.out.println("Min cuts needed for "
                           + "Palindrome Partitioning is " + minPalPartion(str));
    }
}
// This code is contributed by Sumit Ghosh

Python3




# Dynamic Programming Solution for
# Palindrome Partitioning Problem
 
# Returns the minimum number of
# cuts needed to partition a string
# such that every part is a palindrome
def minPalPartion(str):
     
    # Get the length of the string
    n = len(str)
     
    # Create two arrays to build the
    # solution in bottom up manner
    # C[i][j] = Minimum number of cuts
    # needed for palindrome
    # partitioning of substring str[i..j]
    # P[i][j] = true if substring str[i..j]
    # is palindrome, else false. Note that
    # C[i][j] is 0 if P[i][j] is true
    C = [[0 for i in range(n)]
            for i in range(n)]
    P = [[False for i in range(n)]
                for i in range(n)]
 
    # different looping variables
    j = 0
    k = 0
    L = 0
     
    # Every substring of length
    # 1 is a palindrome
    for i in range(n):
        P[i][i] = True;
        C[i][i] = 0;
         
    # L is substring length. Build the
    # solution in bottom-up manner by
    # considering all substrings of
    # length starting from 2 to n.
    # The loop structure is the same as
    # Matrix Chain Multiplication problem 
    # (See https://www.geeksforgeeks.org / matrix-chain-multiplication-dp-8/ )
    for L in range(2, n + 1):
         
        # For substring of length L, set
        # different possible starting indexes
        for i in range(n - L + 1):
            j = i + L - 1 # Set ending index
             
            # If L is 2, then we just need to
            # compare two characters. Else
            # need to check two corner characters
            # and value of P[i + 1][j-1]
            if L == 2:
                P[i][j] = (str[i] == str[j])
            else:
                P[i][j] = ((str[i] == str[j]) and
                             P[i + 1][j - 1])
                              
            # IF str[i..j] is palindrome,
            # then C[i][j] is 0
            if P[i][j] == True:
                C[i][j] = 0
            else:
                 
                # Make a cut at every possible
                # location starting from i to j,
                # and get the minimum cost cut.
                C[i][j] = 100000000
                for k in range(i, j):
                    C[i][j] = min (C[i][j], C[i][k] +
                                   C[k + 1][j] + 1)
                                    
    # Return the min cut value for
    # complete string. i.e., str[0..n-1]
    return C[0][n - 1]
 
# Driver code
str = "ababbbabbababa"
print ('Min cuts needed for Palindrome Partitioning is',
                                     minPalPartion(str))
                                       
# This code is contributed
# by Sahil shelangia

C#




// C# Code for Palindrome Partitioning
// Problem
using System;
 
class GFG {
    // Returns the minimum number of cuts needed
    // to partition a string such that every
    // part is a palindrome
    static int minPalPartion(String str)
    {
        // Get the length of the string
        int n = str.Length;
 
        /* Create two arrays to build the solution
        in bottom up manner
        C[i][j] = Minimum number of cuts needed
                    for palindrome partitioning
                    of substring str[i..j]
        P[i][j] = true if substring str[i..j] is
                    palindrome, else false
        Note that C[i][j] is 0 if P[i][j] is
        true */
        int[, ] C = new int[n, n];
        bool[, ] P = new bool[n, n];
 
        int i, j, k, L; // different looping variables
 
        // Every substring of length 1 is a palindrome
        for (i = 0; i < n; i++) {
            P[i, i] = true;
            C[i, i] = 0;
        }
 
        /* L is substring length. Build the solution in
        bottom up manner by considering all substrings
        of length starting from 2 to n. The loop
        structure is same as Matrx Chain Multiplication
        problem (
        See https:// www.geeksforgeeks.org/matrix-chain-multiplication-dp-8/ )*/
        for (L = 2; L <= n; L++) {
            // For substring of length L, set different
            // possible starting indexes
            for (i = 0; i < n - L + 1; i++) {
                j = i + L - 1; // Set ending index
 
                // If L is 2, then we just need to
                // compare two characters. Else need to
                // check two corner characters and value
                // of P[i+1][j-1]
                if (L == 2)
                    P[i, j] = (str[i] == str[j]);
                else
                    P[i, j] = (str[i] == str[j]) && P[i + 1, j - 1];
 
                // IF str[i..j] is palindrome, then
                // C[i][j] is 0
                if (P[i, j] == true)
                    C[i, j] = 0;
                else {
                    // Make a cut at every possible
                    // localtion starting from i to j,
                    // and get the minimum cost cut.
                    C[i, j] = int.MaxValue;
                    for (k = i; k <= j - 1; k++)
                        C[i, j] = Math.Min(C[i, j], C[i, k]
                                                        + C[k + 1, j] + 1);
                }
            }
        }
 
        // Return the min cut value for complete
        // string. i.e., str[0..n-1]
        return C[0, n - 1];
    }
 
    // Driver program
    public static void Main()
    {
        String str = "ababbbabbababa";
        Console.Write("Min cuts needed for "
                      + "Palindrome Partitioning is " + minPalPartion(str));
    }
}
 
// This code is contributed by Sam007

PHP




<?php
// Dynamic Programming Solution for Palindrome Partitioning Problem
   
// Returns the minimum number of cuts needed to partition a string
// such that every part is a palindrome
function minPalPartion($str)
{
    // Get the length of the string
    $n = strlen($str);
   
    /* Create two arrays to build the solution in bottom up manner
       C[i][j] = Minimum number of cuts needed for palindrome partitioning
                 of substring str[i..j]
       P[i][j] = true if substring str[i..j] is palindrome, else false
       Note that C[i][j] is 0 if P[i][j] is true */
    $C = array_fill(0, $n, array_fill(0, $n, NULL));
    $P = array_fill(false, $n, array_fill(false, $n, NULL));
   
    // Every substring of length 1 is a palindrome
    for ($i=0; $i<$n; $i++)
    {
        $P[$i][$i] = true;
        $C[$i][$i] = 0;
    }
   
    /* L is substring length. Build the solution in a bottom-up manner by
       considering all substrings of length starting from 2 to n.
       The loop structure is same as Matrix Chain Multiplication problem (
    for ($L=2; $L<=$n; $L++)
    {
        // For substring of length L, set different possible starting indexes
        for ($i=0; $i<$n-$L+1; $i++)
        {
            $j = $i+$L-1; // Set ending index
   
            // If L is 2, then we just need to compare two characters. Else
            // need to check two corner characters and value of P[i+1][j-1]
            if ($L == 2)
                $P[$i][$j] = ($str[$i] == $str[$j]);
            else
                $P[$i][$j] = ($str[$i] == $str[$j]) && $P[$i+1][$j-1];
   
            // IF str[i..j] is palindrome, then C[i][j] is 0
            if ($P[$i][$j] == true)
                $C[$i][$j] = 0;
            else
            {
                // Make a cut at every possible location starting from i to j,
                // and get the minimum cost cut.
                $C[$i][$j] = PHP_INT_MAX;
                for ($k=$i; $k<=$j-1; $k++)
                    $C[$i][$j] = min ($C[$i][$j], $C[$i][$k] + $C[$k+1][$j]+1);
            }
        }
    }
   
    // Return the min cut value for complete string. i.e., str[0..n-1]
    return $C[0][$n-1];
}
   
// Driver program to test the above function
 
$str = "ababbbabbababa";
echo "Min cuts needed for Palindrome Partitioning is "
           .minPalPartion($str);
return 0;
?>

Output: 

Min cuts needed for Palindrome Partitioning is 3 

Time Complexity: O(n3)

We can optimize the above code a bit further. Instead of calculating C[i] separately in O(n^2), we can do it with the P[i] itself. Below is the highly optimized code of this problem:

C++




#include <bits/stdc++.h>
using namespace std;
 
int minCut(string a)
{
    int cut[a.length()];
    bool palindrome[a.length()][a.length()];
    memset(palindrome, false, sizeof(palindrome));
    for (int i = 0; i < a.length(); i++)
    {
        int minCut = i;
        for (int j = 0; j <= i; j++)
        {
            if (a[i] == a[j] && (i - j < 2 || palindrome[j + 1][i - 1]))
            {
                palindrome[j][i] = true;
                minCut = min(minCut, j == 0 ? 0 : (cut[j - 1] + 1));
            }
        }
        cut[i] = minCut;
    }
    return cut[a.length() - 1];
}
 
// Driver code
int main()
{
    cout << minCut("aab") << endl;
    cout << minCut("aabababaxx") << endl;
    return 0;
}
 
// This code is contribued by divyesh072019.

Java




import java.io.*;
 
class GFG {
 
    public static int minCut(String a)
    {
        int[] cut = new int[a.length()];
        boolean[][] palindrome = new boolean[a.length()][a.length()];
 
        for (int i = 0; i < a.length(); i++) {
            int minCut = i;
            for (int j = 0; j <= i; j++) {
                if (a.charAt(i) == a.charAt(j) && (i - j < 2 || palindrome[j + 1][i - 1])) {
                    palindrome[j][i] = true;
                    minCut = Math.min(minCut, j == 0 ? 0 : (cut[j - 1] + 1));
                }
            }
            cut[i] = minCut;
        }
 
        return cut[a.length() - 1];
    }
 
    public static void main(String[] args)
    {
        System.out.println(minCut("aab"));
        System.out.println(minCut("aabababaxx"));
    }
}

Python3




def minCut(a):
 
    cut = [0 for i in range(len(a))]
    palindrome = [[False for i in range(len(a))] for j in range(len(a))]
    for i in range(len(a)):
        minCut = i;
        for j in range(i + 1):
            if (a[i] == a[j] and (i - j < 2 or palindrome[j + 1][i - 1])):      
                palindrome[j][i] = True;
                minCut = min(minCut,0 if  j == 0 else (cut[j - 1] + 1));
        cut[i] = minCut;  
    return cut[len(a) - 1];
 
# Driver code
if __name__=='__main__':
 
    print(minCut("aab"))
    print(minCut("aabababaxx"))
     
    # This code is contributed by rutvik_56

C#




using System;
using System.Collections.Generic;  
class GFG
{  
    static int minCut(string a)
    {
        int[] cut = new int[a.Length];
        bool[,] palindrome = new bool[a.Length, a.Length];  
        for (int i = 0; i < a.Length; i++)
        {
            int minCut = i;
            for (int j = 0; j <= i; j++)
            {
                if (a[i] == a[j] && (i - j < 2 ||
                                     palindrome[j + 1, i - 1]))
                {
                    palindrome[j, i] = true;
                    minCut = Math.Min(minCut, j == 0 ? 0 : (cut[j - 1] + 1));
                }
            }
            cut[i] = minCut;
        }
        return cut[a.Length - 1];
    }
   
  // Driver code       
  static void Main()
  {
    Console.WriteLine(minCut("aab"));
    Console.WriteLine(minCut("aabababaxx"));
  }
}
 
// This code is contributed by divyeshrabadiya07.

An optimization to above approach 
In the above approach, we can calculate the minimum cut while finding all palindromic substring. If we find all palindromic substring 1st and then we calculate minimum cut, time complexity will reduce to O(n2). 
Thanks for Vivek for suggesting this optimization. 

C++




// Dynamic Programming Solution for Palindrome Partitioning Problem
#include <limits.h>
#include <stdio.h>
#include <string.h>
 
// A utility function to get minimum of two integers
int min(int a, int b) { return (a < b) ? a : b; }
 
// Returns the minimum number of cuts needed to partition a string
// such that every part is a palindrome
int minPalPartion(char* str)
{
    // Get the length of the string
    int n = strlen(str);
 
    /* Create two arrays to build the solution in bottom-up manner
       C[i] = Minimum number of cuts needed for a palindrome partitioning
                 of substring str[0..i]
       P[i][j] = true if substring str[i..j] is palindrome, else false
       Note that C[i] is 0 if P[0][i] is true */
    int C[n];
    bool P[n][n];
 
    int i, j, k, L; // different looping variables
 
    // Every substring of length 1 is a palindrome
    for (i = 0; i < n; i++) {
        P[i][i] = true;
    }
 
    /* L is substring length. Build the solution in bottom up manner by
       considering all substrings of length starting from 2 to n. */
    for (L = 2; L <= n; L++) {
        // For substring of length L, set different possible starting indexes
        for (i = 0; i < n - L + 1; i++) {
            j = i + L - 1; // Set ending index
 
            // If L is 2, then we just need to compare two characters. Else
            // need to check two corner characters and value of P[i+1][j-1]
            if (L == 2)
                P[i][j] = (str[i] == str[j]);
            else
                P[i][j] = (str[i] == str[j]) && P[i + 1][j - 1];
        }
    }
 
    for (i = 0; i < n; i++) {
        if (P[0][i] == true)
            C[i] = 0;
        else {
            C[i] = INT_MAX;
            for (j = 0; j < i; j++) {
                if (P[j + 1][i] == true && 1 + C[j] < C[i])
                    C[i] = 1 + C[j];
            }
        }
    }
 
    // Return the min cut value for complete string. i.e., str[0..n-1]
    return C[n - 1];
}
 
// Driver program to test above function
int main()
{
    char str[] = "ababbbabbababa";
    printf("Min cuts needed for Palindrome Partitioning is %d",
           minPalPartion(str));
    return 0;
}

Java




// Java Code for Palindrome Partitioning
// Problem
public class GFG {
    // Returns the minimum number of cuts needed
    // to partition a string such that every part
    // is a palindrome
    static int minPalPartion(String str)
    {
        // Get the length of the string
        int n = str.length();
 
        /* Create two arrays to build the solution
        in bottom up manner
           C[i] = Minimum number of cuts needed for
           palindrome partitioning of substring
           str[0..i]
           P[i][j] = true if substring str[i..j] is
           palindrome, else false
           Note that C[i] is 0 if P[0][i] is true */
        int[] C = new int[n];
        boolean[][] P = new boolean[n][n];
 
        int i, j, k, L; // different looping variables
 
        // Every substring of length 1 is a palindrome
        for (i = 0; i < n; i++) {
            P[i][i] = true;
        }
 
        /* L is substring length. Build the solution
        in bottom up manner by considering all substrings
        of length starting from 2 to n. */
        for (L = 2; L <= n; L++) {
            // For substring of length L, set different
            // possible starting indexes
            for (i = 0; i < n - L + 1; i++) {
                j = i + L - 1; // Set ending index
 
                // If L is 2, then we just need to
                // compare two characters. Else need to
                // check two corner characters and value
                // of P[i+1][j-1]
                if (L == 2)
                    P[i][j] = (str.charAt(i) == str.charAt(j));
                else
                    P[i][j] = (str.charAt(i) == str.charAt(j)) && P[i + 1][j - 1];
            }
        }
 
        for (i = 0; i < n; i++) {
            if (P[0][i] == true)
                C[i] = 0;
            else {
                C[i] = Integer.MAX_VALUE;
                for (j = 0; j < i; j++) {
                    if (P[j + 1][i] == true && 1 + C[j] < C[i])
                        C[i] = 1 + C[j];
                }
            }
        }
 
        // Return the min cut value for complete
        // string. i.e., str[0..n-1]
        return C[n - 1];
    }
 
    // Driver program to test above function
    public static void main(String args[])
    {
        String str = "ababbbabbababa";
        System.out.println("Min cuts needed for "
                           + "Palindrome Partitioning"
                           + " is " + minPalPartion(str));
    }
}
// This code is contributed by Sumit Ghosh

Python3




# Dynamic Programming Solution for
# Palindrome Partitioning Problem
import sys
 
# Returns the minimum number of cuts
# needed to partition a string such
# that every part is a palindrome
def minPalPartion(str1):
     
    # Get the length of the string
    n = len(str1);
     
    # Create two arrays to build the solution
    # in bottom up manner
    # C[i] = Minimum number of cuts needed
    # for palindrome partitioning of
    # substring str[0..i]
    # P[i][j] = true if substring str[i..j]
    # is palindrome, else false
    # Note that C[i] is 0 if P[0][i] is true
    C = [0]*(n + 1);
    P = [[False for x in range(n + 1)] for y in range(n + 1)];
     
    # Every substring of length 1 is
    # a palindrome
    for i in range(n):
        P[i][i] = True;
     
    # L is substring length. Build the solution
    # in bottom up manner by considering all
    # substrings of length starting from 2 to n.
    for L in range(2, n + 1):
         
        # For substring of length L, set
        # different possible starting indexes
        for i in range(n - L + 1):
            j = i + L - 1;
             
            # Set ending index
            # If L is 2, then we just need to
            # compare two characters. Else need
            # to check two corner characters and
            # value of P[i + 1][j-1]
            if (L == 2):
                P[i][j] = (str1[i] == str1[j]);
            else:
                P[i][j] = ((str1[i] == str1[j]) and P[i + 1][j - 1]);
    for i in range(n):
        if (P[0][i] == True):
            C[i] = 0;
        else:
            C[i] = sys.maxsize;
            for j in range(i):
                if(P[j + 1][i] == True and 1 + C[j] < C[i]):
                    C[i] = 1 + C[j];
     
    # Return the min cut value for complete
    # string. i.e., str[0..n-1]
    return C[n - 1];
 
# Driver Code
str1 = "ababbbabbababa";
print("Min cuts needed for Palindrome Partitioning is", minPalPartion(str1));
 
# This code is contributed by mits

C#




// C# Code for Palindrome Partitioning
// Problem
using System;
 
class GFG {
 
    // Returns the minimum number of cuts needed
    // to partition a string such that every part
    // is a palindrome
    static int minPalPartion(String str)
    {
        // Get the length of the string
        int n = str.Length;
 
        /* Create two arrays to build the solution
        in bottom up manner
        C[i] = Minimum number of cuts needed for
        palindrome partitioning of substring
        str[0..i]
        P[i][j] = true if substring str[i..j] is
        palindrome, else false
        Note that C[i] is 0 if P[0][i] is true */
        int[] C = new int[n];
        bool[, ] P = new bool[n, n];
 
        int i, j, L; // different looping variables
 
        // Every substring of length 1 is a palindrome
        for (i = 0; i < n; i++) {
            P[i, i] = true;
        }
 
        /* L is substring length. Build the solution
        in bottom up manner by considering all substrings
        of length starting from 2 to n. */
        for (L = 2; L <= n; L++) {
            // For substring of length L, set different
            // possible starting indexes
            for (i = 0; i < n - L + 1; i++) {
                j = i + L - 1; // Set ending index
 
                // If L is 2, then we just need to
                // compare two characters. Else need to
                // check two corner characters and value
                // of P[i+1][j-1]
                if (L == 2)
                    P[i, j] = (str[i] == str[j]);
                else
                    P[i, j] = (str[i] == str[j]) && P[i + 1, j - 1];
            }
        }
 
        for (i = 0; i < n; i++) {
            if (P[0, i] == true)
                C[i] = 0;
            else {
                C[i] = int.MaxValue;
                for (j = 0; j < i; j++) {
                    if (P[j + 1, i] == true && 1 + C[j] < C[i])
                        C[i] = 1 + C[j];
                }
            }
        }
 
        // Return the min cut value for complete
        // string. i.e., str[0..n-1]
        return C[n - 1];
    }
 
    // Driver program
    public static void Main()
    {
        String str = "ababbbabbababa";
        Console.Write("Min cuts needed for "
                      + "Palindrome Partitioning"
                      + " is " + minPalPartion(str));
    }
}
 
// This code is contributed by Sam007

PHP




<?php
// Dynamic Programming Solution for
// Palindrome Partitioning Problem
 
// Returns the minimum number of cuts
// needed to partition a string such
// that every part is a palindrome
function minPalPartion(&$str)
{
     
    // Get the length of the string
    $n = strlen($str);
 
    /* Create two arrays to build the solution
    in bottom up manner
    C[i] = Minimum number of cuts needed
           for palindrome partitioning of
           substring str[0..i]
    P[i][j] = true if substring str[i..j]
    is palindrome, else false
    Note that C[i] is 0 if P[0][i] is true */
    $C = array_fill(0, $n, 0);
    $p = array_fill(0, 10, array_fill(0, 10, 0));
 
    // Every substring of length 1 is
    // a palindrome
    for ($i = 0; $i < $n; $i++)
    {
        $P[$i][$i] = true;
    }
 
    /* L is substring length. Build the solution
    in bottom up manner by considering all
    substrings of length starting from 2 to n. */
    for ($L = 2; $L <= $n; $L++)
    {
        // For substring of length L, set
        // different possible starting indexes
        for ($i = 0; $i < $n - $L + 1; $i++)
        {
            $j = $i + $L - 1; // Set ending index
 
            // If L is 2, then we just need to
            // compare two characters. Else need
            // to check two corner characters and
            // value of P[i+1][j-1]
            if ($L == 2)
                $P[$i][$j] = ($str[$i] == $str[$j]);
            else
                $P[$i][$j] = ($str[$i] == $str[$j]) &&
                              $P[$i + 1][$j - 1];
        }
    }
 
    for ($i = 0; $i < $n; $i++)
    {
        if ($P[0][$i] == true)
            $C[$i] = 0;
        else
        {
            $C[$i] = PHP_INT_MAX;
            for($j = 0; $j < $i; $j++)
            {
                if($P[$j + 1][$i] == true &&
                       1 + $C[$j] < $C[$i])
                    $C[$i] = 1 + $C[$j];
            }
        }
    }
 
    // Return the min cut value for complete
    // string. i.e., str[0..n-1]
    return $C[$n - 1];
}
 
// Driver Code
$str = "ababbbabbababa";
echo "Min cuts needed for Palindrome " .
     "Partitioning is " . minPalPartion($str);
 
// This code is contributed by rathbhupendra
?>

Output: 

Min cuts needed for Palindrome Partitioning is 3 

Time Complexity: O(n2)

Using Memorization to solve this problem. 
The basic idea is to cache the intermittent results calculated in recursive functions. We can put these results into a hashmap/unordered_map. 
To calculate the keys for the Hashmap we will use the starting and end index of the string as the key i.e. [“start_index”.append(“end_index”)] would be the key for the Hashmap. 

Below is the implementation of above approach :  

C++




// Using memoizatoin to solve the partition problem.
#include <bits/stdc++.h>
using namespace std;
// Function to check if input string is pallindrome or not
bool ispallindrome(string input, int start, int end)
{
    // Using two pointer technique to check pallindrome
    while (start < end) {
        if (input[start] != input[end])
            return false;
        start++;
        end--;
    }
    return true;
}
 
// Function to find keys for the Hashmap
string convert(int a, int b)
{
    return to_string(a) + "" + to_string(b);
}
 
// Returns the minimum number of cuts needed to partition a string
// such that every part is a palindrome
int minpalparti_memo(string input, int i, int j, unordered_map<string, int>& memo)
{
    if (i > j)
        return 0;
    // Key for the Input String
    string ij = convert(i, j);
 
    // If the no of partitions for string "ij" is already calculated
    // then return the calculated value using the Hashmap
    if (memo.find(ij) != memo.end()) {
        return memo[ij];
    }
    // Every String of length 1 is a pallindrome
    if (i == j) {
        memo[ij] = 0;
        return 0;
    }
    if (ispallindrome(input, i, j)) {
        memo[ij] = 0;
        return 0;
    }
    int minimum = INT_MAX;
    // Make a cut at every possible location starting from i to j
    for (int k = i; k < j; k++) {
        int left_min = INT_MAX;
        int right_min = INT_MAX;
        string left = convert(i, k);
        string right = convert(k + 1, j);
 
        // If left cut is found already
        if (memo.find(left) != memo.end()) {
            left_min = memo[left];
        }
        // If right cut is found already
        if (memo.find(right) != memo.end()) {
            right_min = memo[right];
        }
 
        // Recursively calculating for left and right strings
        if (left_min == INT_MAX)
            left_min = minpalparti_memo(input, i, k, memo);
        if (right_min == INT_MAX)
            right_min = minpalparti_memo(input, k + 1, j, memo);
 
        // Taking minimum of all k possible cuts
        minimum = min(minimum, left_min + 1 + right_min);
    }
 
    memo[ij] = minimum;
    // Return the min cut value for complete string.
    return memo[ij];
}
int main()
{
    string input = "ababbbabbababa";
    unordered_map<string, int> memo;
    cout << minpalparti_memo(input, 0, input.length() - 1, memo) << endl;
    return 0;
}

Python3




# Using memoizatoin to solve the partition problem.
 
# Function to check if input string is pallindrome or not
def ispallindrome(input, start, end):
 
    # Using two pointer technique to check pallindrome
    while (start < end):
        if (input[start] != input[end]):
            return False;
        start += 1
        end -= 1
    return True;
 
# Function to find keys for the Hashmap
def convert(a, b):
    return str(a) + str(b);
 
# Returns the minimum number of cuts needed to partition a string
# such that every part is a palindrome
def minpalparti_memo(input, i, j, memo):
 
    if (i > j):
        return 0;
       
    # Key for the Input String
    ij = convert(i, j);
 
    # If the no of partitions for string "ij" is already calculated
    # then return the calculated value using the Hashmap
    if (ij in memo):
        return memo[ij];
     
    # Every String of length 1 is a pallindrome
    if (i == j):
        memo[ij] = 0;
        return 0;
    if (ispallindrome(input, i, j)):
        memo[ij] = 0;
        return 0;  
    minimum = 1000000000
     
    # Make a cut at every possible location starting from i to j
    for k in range(i, j):
        left_min = 1000000000
        right_min = 1000000000
        left = convert(i, k);
        right = convert(k + 1, j);
 
        # If left cut is found already
        if (left in memo):
            left_min = memo[left];
         
        # If right cut is found already
        if (right in memo):
            right_min = memo[right];
         
        # Recursively calculating for left and right strings
        if (left_min == 1000000000):
            left_min = minpalparti_memo(input, i, k, memo);
        if (right_min == 1000000000):
            right_min = minpalparti_memo(input, k + 1, j, memo);
 
        # Taking minimum of all k possible cuts
        minimum = min(minimum, left_min + 1 + right_min);
    memo[ij] = minimum;
     
    # Return the min cut value for complete string.
    return memo[ij];
 
  # Driver code
if __name__=='__main__':
 
    input = "ababbbabbababa";
    memo = dict()
    print(minpalparti_memo(input, 0, len(input) - 1, memo))
     
# This code is contributed by Pratham76.

Time Complexity: O(n2)
 

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.

My Personal Notes arrow_drop_up
Recommended Articles
Page :