Skip to content
geeksforgeeks
  • Courses
    • DSA to Development
    • Get IBM Certification
    • Newly Launched!
      • Master Django Framework
      • Become AWS Certified
    • For Working Professionals
      • Interview 101: DSA & System Design
      • Data Science Training Program
      • JAVA Backend Development (Live)
      • DevOps Engineering (LIVE)
      • Data Structures & Algorithms in Python
    • For Students
      • Placement Preparation Course
      • Data Science (Live)
      • Data Structure & Algorithm-Self Paced (C++/JAVA)
      • Master Competitive Programming (Live)
      • Full Stack Development with React & Node JS (Live)
    • Full Stack Development
    • Data Science Program
    • All Courses
  • Tutorials
    • Data Structures & Algorithms
    • ML & Data Science
    • Interview Corner
    • Programming Languages
    • Web Development
    • CS Subjects
    • DevOps And Linux
    • School Learning
  • Practice
    • Build your AI Agent
    • GfG 160
    • Problem of the Day
    • Practice Coding Problems
    • GfG SDE Sheet
  • Contests
    • Accenture Hackathon (Ending Soon!)
    • GfG Weekly [Rated Contest]
    • Job-A-Thon Hiring Challenge
    • All Contests and Events
  • DSA
  • Interview Problems on DP
  • Practice DP
  • MCQs on DP
  • Tutorial on Dynamic Programming
  • Optimal Substructure
  • Overlapping Subproblem
  • Memoization
  • Tabulation
  • Tabulation vs Memoization
  • 0/1 Knapsack
  • Unbounded Knapsack
  • Subset Sum
  • LCS
  • LIS
  • Coin Change
  • Word Break
  • Egg Dropping Puzzle
  • Matrix Chain Multiplication
  • Palindrome Partitioning
  • DP on Arrays
  • DP with Bitmasking
  • Digit DP
  • DP on Trees
  • DP on Graph
Open In App
Next Article:
Palindrome pair in an array of words (or strings)
Next article icon

Palindrome Partitioning

Last Updated : 26 Mar, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report
Try it on GfG Practice
redirect icon

Given a string s, the task is to find the minimum number of cuts needed for palindrome partitioning of the given string. A partitioning of the string is a palindrome partitioning if every sub-string of the partition is a palindrome.

Examples: 

Input: s = “geek” 
Output: 2 
Explanation: We need to make minimum 2 cuts, i.e., “g | ee | k”.

Input: s= “aaaa” 
Output: 0 
Explanation: The string is already a palindrome.

Input: s = “ababbbabbababa” 
Output: 3
Explanation: We need to make minimum 3 cuts, i.e., “aba | bb | babbab | aba”.

Table of Content

  • [Naive Approach] Using Recursion – O(n*2^n) Time and O(n) Space
  • [Better Approach 1] Using Top-Down DP (Memoization) – O(n^3) Time and O(n^2) Space
  • [Better Approach 2] Using Bottom-Up DP (Tabulation) – O(n^3) Time and O(n^2) Space
  • [Expected Approach] Using Optimised Bottom-Up DP (Tabulation) – O(n^2) Time and O(n^2) Space

[Naive Approach] Using Recursion – O(n*2^n) Time and O(n) Space

In this approach, we will try to apply all possible partitions and at the end return the correct combination of partitions.

This approach is similar to that of Matrix Chain Multiplication problem.

In this approach, we recursively evaluate the following conditions:

  • Base Case: If the current string is a palindrome, then we simply return 0, no Partitioning is required.
  • Else, like the Matrix Chain Multiplication problem,
    • we try making cuts at all possible places,
    • recursively calculate the cost for each cut
    • return the minimum value.
C++
// C++ Program for Palindrome Partitioning Problem // using Recursion #include <iostream> #include <vector> #include <limits.h> using namespace std;  // Function to Check if a substring is a palindrome bool isPalindrome(string& s, int i, int j) {     while (i < j) {         if (s[i] != s[j])             return false;         i++;         j--;     }     return true; }  // Recursive Function to find the minimum number of  // cuts needed for palindrome partitioning int palPartitionRec(string& s, int i, int j) {        // Base case: If the substring is empty or    	// a palindrome, no cuts needed     if (i >= j || isPalindrome(s, i, j))         return 0;      int res = INT_MAX, cuts;      // Iterate through all possible partitions and    	// find the minimum cuts needed     for (int k = i; k < j; k++) {         cuts = 1 + palPartitionRec(s, i, k)                 	+ palPartitionRec(s, k + 1, j);         res = min(res, cuts);     }      return res; }  int palPartition(string &s) {   	return palPartitionRec(s, 0, s.size()-1); }  int main() {     string s = "geek";      cout << palPartition(s) << endl;     return 0; } 
C
// C Program for Palindrome Partitioning Problem // using Recursion #include <stdio.h> #include <string.h> #include <limits.h>  // Function to check if a substring is a palindrome int isPalindrome(char* s, int i, int j) {     while (i < j) {         if (s[i] != s[j])             return 0;         i++;         j--;     }     return 1; }  // Recursive function to find the minimum number  // of cuts needed for palindrome partitioning int palPartitionRec(char* s, int i, int j) {        // Base case: If the substring is empty    	// or a palindrome, no cuts needed     if (i >= j || isPalindrome(s, i, j))         return 0;      int res = INT_MAX, cuts;      // Iterate through all possible partitions    	// and find the minimum cuts needed     for (int k = i; k < j; k++) {         cuts = 1 + palPartitionRec(s, i, k) + palPartitionRec(s, k + 1, j);         if (cuts < res) res = cuts;     }      return res; }  int palPartition(char* s) {     return palPartitionRec(s, 0, strlen(s) - 1); }  int main() {     char s[] = "geek";     printf("%d\n", palPartition(s));     return 0; } 
Java
// Java Program for Palindrome Partitioning Problem // using Recursion import java.util.*;  class GfG {      // Function to check if a substring is a palindrome     static boolean isPalindrome(String s, int i, int j) {         while (i < j) {             if (s.charAt(i) != s.charAt(j))                 return false;             i++;             j--;         }         return true;     }      // Recursive function to find the minimum number of    	// cuts needed for palindrome partitioning     static int palPartitionRec(String s, int i, int j) {                // Base case: If the substring is empty       	// or a palindrome, no cuts needed         if (i >= j || isPalindrome(s, i, j))             return 0;          int res = Integer.MAX_VALUE, cuts;          // Iterate through all possible partitions        	// and find the minimum cuts needed         for (int k = i; k < j; k++) {             cuts = 1 + palPartitionRec(s, i, k) +                			palPartitionRec(s, k + 1, j);             res = Math.min(res, cuts);         }          return res;     }      static int palPartition(String s) {         return palPartitionRec(s, 0, s.length() - 1);     }      public static void main(String[] args) {         String s = "geek";         System.out.println(palPartition(s));     } } 
Python
# Python Program for Palindrome Partitioning Problem # using Recursion import sys  # Function to check if a substring is a palindrome def isPalindrome(s, i, j):     while i < j:         if s[i] != s[j]:             return False         i += 1         j -= 1     return True  # Recursive function to find the minimum number  # of cuts needed for palindrome partitioning def palPartitionRec(s, i, j):        # Base case: If the substring is empty      # or a palindrome, no cuts needed     if i >= j or isPalindrome(s, i, j):         return 0      res = sys.maxsize      # Iterate through all possible partitions      # and find the minimum cuts needed     for k in range(i, j):         cuts = 1 + palPartitionRec(s, i, k) \         		 + palPartitionRec(s, k + 1, j)         res = min(res, cuts)      return res  def palPartition(s):     return palPartitionRec(s, 0, len(s) - 1)  if __name__ == "__main__":     s = "geek"     print(palPartition(s)) 
C#
// C# Program for Palindrome Partitioning Problem // using Recursion using System;  class GfG {      // Function to check if a substring is a palindrome     static bool isPalindrome(string s, int i, int j) {         while (i < j) {             if (s[i] != s[j])                 return false;             i++;             j--;         }         return true;     }      // Recursive function to find the minimum number of    	// cuts needed for palindrome partitioning     static int palPartitionRec(string s, int i, int j) {                // Base case: If the substring is empty        	// or a palindrome, no cuts needed         if (i >= j || isPalindrome(s, i, j))             return 0;          int res = int.MaxValue, cuts;          // Iterate through all possible partitions        	// and find the minimum cuts needed         for (int k = i; k < j; k++) {             cuts = 1 + palPartitionRec(s, i, k)                			+ palPartitionRec(s, k + 1, j);             res = Math.Min(res, cuts);         }          return res;     }      static int palPartition(string s) {         return palPartitionRec(s, 0, s.Length - 1);     }      static void Main() {         string s = "geek";         Console.WriteLine(palPartition(s));     } } 
JavaScript
// JavaScript Program for Palindrome Partitioning Problem // using Recursion  // Function to check if a substring is a palindrome function isPalindrome(s, i, j) {     while (i < j) {         if (s[i] !== s[j])             return false;         i++;         j--;     }     return true; }  // Recursive function to find the minimum number  // of cuts needed for palindrome partitioning function palPartitionRec(s, i, j) {      // Base case: If the substring is empty      // or a palindrome, no cuts needed     if (i >= j || isPalindrome(s, i, j))         return 0;      let res = Number.MAX_SAFE_INTEGER, cuts;      // Iterate through all possible partitions      // and find the minimum cuts needed     for (let k = i; k < j; k++) {         cuts = 1 + palPartitionRec(s, i, k)          			+ palPartitionRec(s, k + 1, j);         res = Math.min(res, cuts);     }      return res; }  function palPartition(s) {     return palPartitionRec(s, 0, s.length - 1); }  // Driver Code  const s = "geek"; console.log(palPartition(s)); 

Output
2 

[Better Approach 1] Using Top-Down DP (Memoization) – O(n^3) Time and O(n^2) Space

The above recursive approach has overlapping subproblems, leading to redundant computations thereby resulting in exponential time complexity. This redundant computation can be solved by using Memoization.

To avoid redundant computations, we can memoize results of each subproblem and reuse them as needed. A 2D array can serve as a memoization table to store solutions for overlapping subproblems. The size of this memo table will be n*n, as there are n possible starting indices and n possible ending indices for any subarray.

C++
// C++ Program for Palindrome Partitioning Problem // Using Top-Down DP #include <iostream> #include <vector> #include <limits.h> using namespace std;  // Function to Check if a substring is a palindrome bool isPalindrome(string& s, int i, int j) {     while (i < j) {         if (s[i] != s[j])             return false;         i++;         j--;     }     return true; }  // Recursive Function to find the minimum number of  // cuts needed for palindrome partitioning int palPartitionRec(string& s, int i, int j,                      	vector<vector<int>>& memo) {   	   	// check in memo for    	if (memo[i][j] != -1)        	return memo[i][j];        // Base case: If the substring is empty or    	// a palindrome, no cuts needed     if (i >= j || isPalindrome(s, i, j))         return memo[i][j] = 0;      int res = INT_MAX, cuts;      // Iterate through all possible partitions and    	// find the minimum cuts needed     for (int k = i; k < j; k++) {         cuts = 1 + palPartitionRec(s, i, k, memo)                 + palPartitionRec(s, k + 1, j, memo);         res = min(res, cuts);     }      return memo[i][j] = res; }  int palPartition(string &s) {   	int n = s.size();      	// declare a memo array to store the result   	// and initialise it with -1   	vector<vector<int>> memo(n, vector<int> (n, -1));      	return palPartitionRec(s, 0, n - 1, memo); }  int main() {     string s = "geek";      cout << palPartition(s) << endl;     return 0; } 
Java
// Java Program for Palindrome Partitioning Problem // Using Top-Down DP import java.util.Arrays;  class GfG {      // Function to check if a substring is a palindrome     static boolean isPalindrome(String s, int i, int j) {         while (i < j) {             if (s.charAt(i) != s.charAt(j))                  return false;             i++;             j--;         }         return true;     }      // Recursive function to find the minimum number of    	// cuts needed for palindrome partitioning     static int palPartitionRec(String s, int i, int j, int[][] memo) {                // check in memo for previously computed results         if (memo[i][j] != -1)              return memo[i][j];          // Base case: If the substring is empty or        	// a palindrome, no cuts needed         if (i >= j || isPalindrome(s, i, j))              return memo[i][j] = 0;          int res = Integer.MAX_VALUE, cuts;          // Iterate through all possible partitions and       	// find the minimum cuts needed         for (int k = i; k < j; k++) {             cuts = 1 + palPartitionRec(s, i, k, memo)                		 + palPartitionRec(s, k + 1, j, memo);             res = Math.min(res, cuts);         }          return memo[i][j] = res;     }      static int palPartition(String s) {         int n = s.length();         int[][] memo = new int[n][n];                  // Initialize memo array with -1         for (int[] row : memo)             Arrays.fill(row, -1);                  return palPartitionRec(s, 0, n - 1, memo);     }      public static void main(String[] args) {         String s = "geek";         System.out.println(palPartition(s));     } } 
Python
# Python Program for Palindrome Partitioning Problem # Using Top-Down DP import sys  # Function to check if a substring is a palindrome def isPalindrome(s, i, j):     while i < j:         if s[i] != s[j]:             return False         i += 1         j -= 1     return True  # Recursive function to find the minimum number of # cuts needed for palindrome partitioning def palPartitionRec(s, i, j, memo):        # Check memo for previously computed results     if memo[i][j] != -1:         return memo[i][j]      # Base case: If the substring is empty or      # a palindrome, no cuts needed     if i >= j or isPalindrome(s, i, j):         memo[i][j] = 0         return 0      res = sys.maxsize      # Iterate through all possible partitions and     # find the minimum cuts needed     for k in range(i, j):         cuts = 1 + palPartitionRec(s, i, k, memo) \         + palPartitionRec(s, k + 1, j, memo)         res = min(res, cuts)      memo[i][j] = res     return res  def palPartition(s):     n = len(s)     memo = [[-1 for _ in range(n)] for _ in range(n)]     return palPartitionRec(s, 0, n - 1, memo)  if __name__ == "__main__":     s = "geek"     print(palPartition(s)) 
C#
// C# Program for Palindrome Partitioning Problem // Usin Top-Down DP using System;  class GfG {      // Function to check if a substring is a palindrome     static bool isPalindrome(string s, int i, int j) {         while (i < j) {             if (s[i] != s[j])                  return false;             i++;             j--;         }         return true;     }      // Recursive function to find the minimum number of    	// cuts needed for palindrome partitioning        static int palPartitionRec(string s, int i,                                 	int j, int[,] memo) {                // Check memo for previously computed results         if (memo[i, j] != -1)              return memo[i, j];          // Base case: If the substring is empty        	// or a palindrome, no cuts needed         if (i >= j || isPalindrome(s, i, j))              return memo[i, j] = 0;          int res = int.MaxValue, cuts;          // Iterate through all possible partitions        	// and find the minimum cuts needed         for (int k = i; k < j; k++) {             cuts = 1 + palPartitionRec(s, i, k, memo)                	+ palPartitionRec(s, k + 1, j, memo);             res = Math.Min(res, cuts);         }          return memo[i, j] = res;     }      static int palPartition(string s) {         int n = s.Length;         int[,] memo = new int[n, n];          // Initialize memo array with -1         for (int i = 0; i < n; i++)             for (int j = 0; j < n; j++)                 memo[i, j] = -1;          return palPartitionRec(s, 0, n - 1, memo);     }      static void Main() {         string s = "geek";         Console.WriteLine(palPartition(s));     } } 
JavaScript
// JavaScript Program for Palindrome Partitioning Problem // Using Top-Down DP  // Function to check if a substring is a palindrome function isPalindrome(s, i, j) {     while (i < j) {         if (s[i] !== s[j])             return false;         i++;         j--;     }     return true; }  // Recursive function to find the minimum number of  // cuts needed for palindrome partitioning function palPartitionRec(s, i, j, memo) {      // Check memo for previously computed results     if (memo[i][j] !== -1)          return memo[i][j];      // Base case: If the substring is empty or      // a palindrome, no cuts needed     if (i >= j || isPalindrome(s, i, j))         return memo[i][j] = 0;      let res = Infinity, cuts;      // Iterate through all possible partitions      // and find the minimum cuts needed     for (let k = i; k < j; k++) {         cuts = 1 + palPartitionRec(s, i, k, memo)          		+ palPartitionRec(s, k + 1, j, memo);         res = Math.min(res, cuts);     }      return memo[i][j] = res; }  function palPartition(s) {     const n = s.length;     const memo = Array.from({ length: n },      				() => Array(n).fill(-1));     return palPartitionRec(s, 0, n - 1, memo); }  // Driver Code const s = "geek"; console.log(palPartition(s)); 

Output
2 

[Better Approach 2] Using Bottom-Up DP (Tabulation) – O(n^3) Time and O(n^2) Space

The approach is similar to the previous one; just instead of breaking down the problem recursively, we iteratively build up the solution by calculating in bottom-up manner.

Here, we can use two 2D array dp[][] and isPalin[][], for storing the computed result.

  • dp[i][j] stores the minimum cuts for palindrome partitioning of the substring s[i … j]
  • isPalin[i][j] tells us whether substring s[i … j] is a palindromic string or not.

We starts with smaller substrings and gradually builds up to the result for entire string.

C++
// C++ Solution for Palindrome Partitioning Problem // using Bottom Up Dynamic Programming #include <iostream> #include <vector> #include <climits> using namespace std;  // Function to find the minimum number of cuts  // needed to partition a string such that  // every part is a palindrome int palPartition(string& s) {     int n = s.length();      // dp[i][j] = Minimum number of cuts needed for     // palindrome partitioning of substring s[i..j]     int dp[n][n];      // isPalin[i][j] = true if substring s[i..j]    	// is palindrome,else false     bool isPalin[n][n];      // Every substring of length 1 is a palindrome     for (int i = 0; i < n; i++) {         isPalin[i][i] = true;         dp[i][i] = 0;     }      for (int len = 2; len <= n; len++) {          // Build solution for all substrings s[i ... j]        	// of length len         for (int i = 0, j = i + len - 1; j < n ; i++, j++) {                        // If len is 2, then we just need to             // compare two characters.              if (len == 2)                 isPalin[i][j] = (s[i] == s[j]);                      	// Else need to check two corner characters             // and value of isPalin[i+1][j-1]             else                 isPalin[i][j] = (s[i] == s[j]) &&                						isPalin[i + 1][j - 1];              // IF s[i..j] is palindrome, then dp[i][j] is 0             if (isPalin[i][j] == true)                 dp[i][j] = 0;             else {              // Make a cut at every possible location starting            	// from i to j, and get the minimum cost cut.                 dp[i][j] = INT_MAX;                 for (int k = i; k <= j - 1; k++)                     dp[i][j] = min(dp[i][j], 1 +                                     dp[i][k] + dp[k + 1][j]);             }         }     }      // Return the min cut value for     // complete string. i.e., s[0..n-1]     return dp[0][n - 1]; }  int main() {     string s = "geek";      cout << palPartition(s) << endl;     return 0; } 
Java
// Java Solution for Palindrome Partitioning Problem // using Bottom Up Dynamic Programming import java.util.Arrays;  class GfG {      // Function to find the minimum number of cuts      // needed to partition a string such that      // every part is a palindrome     static int palPartition(String s) {         int n = s.length();          // dp[i][j] = Minimum number of cuts needed for         // palindrome partitioning of substring s[i..j]         int[][] dp = new int[n][n];          // isPalin[i][j] = true if substring s[i..j]          // is palindrome, else false         boolean[][] isPalin = new boolean[n][n];          // Every substring of length 1 is a palindrome         for (int i = 0; i < n; i++) {             isPalin[i][i] = true;             dp[i][i] = 0;         }          for (int len = 2; len <= n; len++) {              // Build solution for all  substrings s[i ... j]              // of length len             for (int i = 0, j = i + len - 1; j < n; i++, j++) {                  // If len is 2, then we just need to                 // compare two characters.                 if (len == 2)                     isPalin[i][j] = (s.charAt(i) == s.charAt(j));                  // Else need to check two corner characters                 // and value of isPalin[i+1][j-1]                 else                     isPalin[i][j] = (s.charAt(i) == s.charAt(j))                    						&& isPalin[i + 1][j - 1];                  // IF s[i..j] is palindrome, then dp[i][j] is 0                 if (isPalin[i][j])                     dp[i][j] = 0;                 else {                      // Make a cut at every possible location starting                      // from i to j, and get the minimum cost cut.                     dp[i][j] = Integer.MAX_VALUE;                     for (int k = i; k <= j - 1; k++)                         dp[i][j] = Math.min(dp[i][j], 1 +                                            dp[i][k] + dp[k + 1][j]);                 }             }         }          // Return the min cut value for         // complete string. i.e., s[0..n-1]         return dp[0][n - 1];     }      public static void main(String[] args) {         String s = "geek";         System.out.println(palPartition(s));     } } 
Python
# Python Solution for Palindrome Partitioning Problem # using Bottom Up Dynamic Programming  # Function to find the minimum number of cuts  # needed to partition a string such that  # every part is a palindrome def palPartition(s):     n = len(s)      # dp[i][j] = Minimum number of cuts needed for     # palindrome partitioning of substring s[i..j]     dp = [[0] * n for _ in range(n)]      # isPalin[i][j] = true if substring s[i..j]      # is palindrome, else false     isPalin = [[False] * n for _ in range(n)]      # Every substring of length 1 is a palindrome     for i in range(n):         isPalin[i][i] = True         dp[i][i] = 0      for length in range(2, n + 1):          # Build solution for all  substrings s[i ... j]          # of length len         for i in range(n - length + 1):             j = i + length - 1              # If len is 2, then we just need to             # compare two characters.             if length == 2:                 isPalin[i][j] = (s[i] == s[j])                              # Else need to check two corner characters             # and value of isPalin[i+1][j-1]             else:                 isPalin[i][j] = (s[i] == s[j]) and isPalin[i + 1][j - 1]              # IF s[i..j] is palindrome, then dp[i][j] is 0             if isPalin[i][j]:                 dp[i][j] = 0             else:                 # Make a cut at every possible location starting                  # from i to j, and get the minimum cost cut.                 dp[i][j] = min(1 + dp[i][k] + dp[k + 1][j] for k in range(i, j))      # Return the min cut value for     # complete string. i.e., s[0..n-1]     return dp[0][n - 1]  if __name__ == "__main__":     s = "geek"     print(palPartition(s)) 
C#
// C# Solution for Palindrome Partitioning Problem // using Bottom Up Dynamic Programming using System;  class GfG {      // Function to find the minimum number of cuts      // needed to partition a string such that      // every part is a palindrome     static int palPartition(string s) {         int n = s.Length;          // dp[i][j] = Minimum number of cuts needed for         // palindrome partitioning of substring s[i..j]         int[,] dp = new int[n, n];          // isPalin[i][j] = true if substring s[i..j]          // is palindrome, else false         bool[,] isPalin = new bool[n, n];          // Every substring of length 1 is a palindrome         for (int i = 0; i < n; i++) {             isPalin[i, i] = true;             dp[i, i] = 0;         }          for (int len = 2; len <= n; len++) {              // Build solution for all substrings s[i ... j]              // of length len             for (int i = 0, j = i + len - 1; j < n; i++, j++) {                  // If len is 2, then we just need to                 // compare two characters.                 if (len == 2)                     isPalin[i, j] = (s[i] == s[j]);                  // Else need to check two corner characters                 // and value of isPalin[i+1][j-1]                 else                     isPalin[i, j] = (s[i] == s[j]) &&                    						isPalin[i + 1, j - 1];                  // IF s[i..j] is palindrome, then dp[i][j] is 0                 if (isPalin[i, j])                     dp[i, j] = 0;                 else {                      // Make a cut at every possible location starting                      // from i to j, and get the minimum cost cut.                     dp[i, j] = int.MaxValue;                     for (int k = i; k <= j - 1; k++)                         dp[i, j] = Math.Min(dp[i, j], 1 +                                              dp[i, k] + dp[k + 1, j]);                 }             }         }          // Return the min cut value for         // complete string. i.e., s[0..n-1]         return dp[0, n - 1];     }      static void Main() {         string s = "geek";         Console.WriteLine(palPartition(s));     } } 
JavaScript
// JavaScript Solution for Palindrome Partitioning Problem // using Bottom Up Dynamic Programming  // Function to find the minimum number of cuts  // needed to partition a string such that  // every part is a palindrome function palPartition(s) {     let n = s.length;      // dp[i][j] = Minimum number of cuts needed for     // palindrome partitioning of substring s[i..j]     let dp = Array.from({ length: n },      							() => Array(n).fill(0));      // isPalin[i][j] = true if substring s[i..j]      // is palindrome, else false     let isPalin = Array.from({ length: n },      						() => Array(n).fill(false));      // Every substring of length 1 is a palindrome     for (let i = 0; i < n; i++) {         isPalin[i][i] = true;         dp[i][i] = 0;     }      for (let len = 2; len <= n; len++) {          // Build solution for all substrings s[i ... j]          // of length len         for (let i = 0; i <= n - len; i++) {             let j = i + len - 1;              // If len is 2, then we just need to             // compare two characters.             if (len === 2)                 isPalin[i][j] = (s[i] === s[j]);              // Else need to check two corner characters             // and value of isPalin[i+1][j-1]             else                 isPalin[i][j] = (s[i] === s[j]) &&  									isPalin[i + 1][j - 1];              // IF s[i..j] is palindrome, then dp[i][j] is 0             if (isPalin[i][j])                 dp[i][j] = 0;             else {                  // Make a cut at every possible location starting                  // from i to j, and get the minimum cost cut.                 dp[i][j] = Infinity;                 for (let k = i; k <= j - 1; k++)                     dp[i][j] = Math.min(dp[i][j], 1 +                      		dp[i][k] + dp[k + 1][j]);             }         }     }      // Return the min cut value for     // complete string. i.e., s[0..n-1]     return dp[0][n - 1]; }  // Driver Code  let s = "geek"; console.log(palPartition(s)); 

Output
2 

[Expected Approach] Using Optimized Bottom-Up DP (Tabulation) – O(n^2) Time and O(n^2) Space

Here we precompute a palindrome table isPalin[][], where isPalin[i][j] = true if s[i..j] is a palindrome. This helps efficiently check palindrome partitions. Then we fill dp[], where dp[i] stores the minimum cuts needed to partition s[0..i] into palindromic substrings. If s[0..i] is a palindrome, no cut is needed (dp[i] = 0). Otherwise, we check all valid partitions and update dp[i] accordingly.

To fill dp[i], we find the suffix starting from j and ending at index i, (1 <= j <= i <= n – 1), which are palindromes. Hence, we can make a cut here that requires 1 + min cut from rest substring [0, j – 1]. For all such palindromic suffixes starting at j and ending at i, keep minimizing in dp[i]. Similarly, we need to compute results for all such i. (1 <= i <= n – 1) and finally, dp[n – 1] will be the minimum number of cuts needed for palindrome partitioning of the given string.

C++
// C++ Solution for Palindrome Partitioning Problem // using Optimised Bottom Up Dynamic Programming #include <iostream> #include <vector> #include <climits> using namespace std;  // Function to fill isPalin array such that isPalin[i][j]  // stores whether substring s[i, j] is a palindrome or not void generatePal(string& s, vector<vector<bool>>& isPalin) {     int n = s.size();      // Substring s[i .. i] of len 1    	// is always palindromic     for (int i = 0; i < n; i++) {         isPalin[i][i] = true;     }      // Iterate over different lengths of substrings     for (int len = 2; len <= n; len++) {                for (int i = 0, j = i + len - 1; j < n ; i++, j++) {                        // Check whether s[i] == s[j] and the             // substring between them is a palindrome             if (s[i] == s[j] && (len == 2                                   || isPalin[i + 1][j - 1])) {                  // Mark the substring from i to j as a                 // palindrome                 isPalin[i][j] = true;             }         }     } }  // Function to calculate the minimum number of cuts required // to make all substrings of 's' palindromic int palPartition(string& s) {     int n = s.size();      // 2D array to store whether substring    	// s[i, j] is a palindrome or not     vector<vector<bool>> isPalin(n, vector<bool>(n, false));      generatePal(s, isPalin);      // dp[i] stores minimum cuts for Palindrome    	// Partitioning of substring s[0...i]      vector<int> dp(n, n);      // There is no cut required for single character     // as it is always palindrome     dp[0] = 0;      // Iterate over the given string     for (int i = 1; i < n; i++) {          // Check if string 0 to i is palindrome.         if (isPalin[0][i]) {                      	// if palindrome then cuts required is 0             dp[i] = 0;         }         else {             for (int j = i; j >= 1; j--) {                              	// if substring s[j...i] is palindromic               	// then we can make a cut over here                 if (isPalin[j][i]) {                    	// update dp[i] with minimum cuts                   	dp[i] = min(dp[i], 1 + dp[j-1]);                 }             }         }     }      // Return the minimum cuts required    	// for the entire string 's'   	     return dp[n - 1];      }  int main() {     string s = "geek";      cout << palPartition(s) << endl;     return 0; } 
Java
// Java Solution for Palindrome Partitioning Problem // using Optimised Bottom Up Dynamic Programming import java.util.Arrays;  class GfG {      // Function to fill isPalin array such that isPalin[i][j]      // stores whether substring s[i, j] is a palindrome or not     static void generatePal(String s, boolean[][] isPalin) {         int n = s.length();          // Substring s[i .. i] of len 1          // is always palindromic         for (int i = 0; i < n; i++) {             isPalin[i][i] = true;         }          // Iterate over different lengths of substrings         for (int len = 2; len <= n; len++) {             for (int i = 0, j = i + len - 1; j < n; i++, j++) {                  // Check whether s[i] == s[j] and the                 // substring between them is a palindrome                 if (s.charAt(i) == s.charAt(j) &&                      (len == 2 || isPalin[i + 1][j - 1])) {                      // Mark the substring from i to j as a                     // palindrome                     isPalin[i][j] = true;                 }             }         }     }      // Function to calculate the minimum number of cuts required     // to make all substrings of 's' palindromic     static int palPartition(String s) {         int n = s.length();          // 2D array to store whether substring          // s[i, j] is a palindrome or not         boolean[][] isPalin = new boolean[n][n];          generatePal(s, isPalin);          // dp[i] stores minimum cuts for Palindrome          // Partitioning of substring s[0...i]          int[] dp = new int[n];         Arrays.fill(dp, n);          // There is no cut required for single character         // as it is always palindrome         dp[0] = 0;          // Iterate over the given string         for (int i = 1; i < n; i++) {              // Check if string 0 to i is palindrome.             if (isPalin[0][i]) {                  // if palindrome then cuts required is 0                 dp[i] = 0;             } else {                 for (int j = i; j >= 1; j--) {                      // if substring s[j...i] is palindromic                     // then we can make a cut over here                     if (isPalin[j][i]) {                          // update dp[i] with minimum cuts                         dp[i] = Math.min(dp[i], 1 + dp[j - 1]);                     }                 }             }         }          // Return the minimum cuts required          // for the entire string 's'         return dp[n - 1];     }      public static void main(String[] args) {         String s = "geek";         System.out.println(palPartition(s));     } } 
Python
# Python Solution for Palindrome Partitioning Problem # using Optimised Bottom Up Dynamic Programming  # Function to fill isPalin array such that isPalin[i][j]  # stores whether substring s[i, j] is a palindrome or not def generatePal(s, isPalin):     n = len(s)      # Substring s[i .. i] of len 1      # is always palindromic     for i in range(n):         isPalin[i][i] = True      # Iterate over different lengths of substrings     for length in range(2, n + 1):         for i in range(n - length + 1):             j = i + length - 1              # Check whether s[i] == s[j] and the             # substring between them is a palindrome             if s[i] == s[j] and (length == 2 or isPalin[i + 1][j - 1]):                                # Mark the substring from i to j as a                 # palindrome                 isPalin[i][j] = True  # Function to calculate the minimum number of cuts required # to make all substrings of 's' palindromic def palPartition(s):     n = len(s)      # 2D array to store whether substring      # s[i, j] is a palindrome or not     isPalin = [[False] * n for _ in range(n)]      generatePal(s, isPalin)      # dp[i] stores minimum cuts for Palindrome      # Partitioning of substring s[0...i]      dp = [n] * n      # There is no cut required for single character     # as it is always palindrome     dp[0] = 0      # Iterate over the given string     for i in range(1, n):          # Check if string 0 to i is palindrome.         if isPalin[0][i]:                        # if palindrome then cuts required is 0             dp[i] = 0         else:             for j in range(i, 0, -1):                  # if substring s[j...i] is palindromic                 # then we can make a cut over here                 if isPalin[j][i]:                                        # update dp[i] with minimum cuts                     dp[i] = min(dp[i], 1 + dp[j - 1])      # Return the minimum cuts required      # for the entire string 's'     return dp[n - 1]  if __name__ == "__main__":     s = "geek"     print(palPartition(s)) 
C#
// C# Solution for Palindrome Partitioning Problem // using Optimised Bottom Up Dynamic Programming using System;  class GfG {      // Function to fill isPalin array such that isPalin[i][j]      // stores whether substring s[i, j] is a palindrome or not     static void GeneratePal(string s, bool[,] isPalin) {         int n = s.Length;          // Substring s[i .. i] of len 1          // is always palindromic         for (int i = 0; i < n; i++) {             isPalin[i, i] = true;         }          // Iterate over different lengths of substrings         for (int len = 2; len <= n; len++) {             for (int i = 0, j = i + len - 1; j < n; i++, j++) {                  // Check whether s[i] == s[j] and the                 // substring between them is a palindrome                 if (s[i] == s[j] && (len == 2 || isPalin[i + 1, j - 1])) {                      // Mark the substring from i to j as a                     // palindrome                     isPalin[i, j] = true;                 }             }         }     }      // Function to calculate the minimum number of cuts required     // to make all substrings of 's' palindromic     static int palPartition(string s) {         int n = s.Length;          // 2D array to store whether substring          // s[i, j] is a palindrome or not         bool[,] isPalin = new bool[n, n];          GeneratePal(s, isPalin);          // dp[i] stores minimum cuts for Palindrome          // Partitioning of substring s[0...i]          int[] dp = new int[n];         Array.Fill(dp, n);          // There is no cut required for single character         // as it is always palindrome         dp[0] = 0;          // Iterate over the given string         for (int i = 1; i < n; i++) {              // Check if string 0 to i is palindrome.             if (isPalin[0, i]) {                                // if palindrome then cuts required is 0                 dp[i] = 0;             } else {                 for (int j = i; j >= 1; j--) {                      // if substring s[j...i] is palindromic                     // then we can make a cut over here                     if (isPalin[j, i]) {                          // update dp[i] with minimum cuts                         dp[i] = Math.Min(dp[i], 1 + dp[j - 1]);                     }                 }             }         }          // Return the minimum cuts required          // for the entire string 's'         return dp[n - 1];     }      static void Main() {         string s = "geek";         Console.WriteLine(palPartition(s));     } } 
JavaScript
// JavaScript Solution for Palindrome Partitioning Problem // using Optimised Bottom Up Dynamic Programming  // Function to fill isPalin array such that isPalin[i][j]  // stores whether substring s[i, j] is a palindrome or not function generatePal(s, isPalin) {     let n = s.length;      // Substring s[i .. i] of len 1      // is always palindromic     for (let i = 0; i < n; i++) {         isPalin[i][i] = true;     }      // Iterate over different lengths of substrings     for (let len = 2; len <= n; len++) {         for (let i = 0, j = i + len - 1; j < n; i++, j++) {              // Check whether s[i] == s[j] and the             // substring between them is a palindrome             if (s[i] === s[j] && (len === 2 || isPalin[i + 1][j - 1])) {                  // Mark the substring from i to j as a                 // palindrome                 isPalin[i][j] = true;             }         }     } }  // Function to calculate the minimum number of cuts required // to make all substrings of 's' palindromic function palPartition(s) {     let n = s.length;      // 2D array to store whether substring      // s[i, j] is a palindrome or not     let isPalin = Array.from({ length: n },      					() => Array(n).fill(false));      generatePal(s, isPalin);      // dp[i] stores minimum cuts for Palindrome      // Partitioning of substring s[0...i]      let dp = new Array(n).fill(n);      // There is no cut required for single character     // as it is always palindrome     dp[0] = 0;      // Iterate over the given string     for (let i = 1; i < n; i++) {          // Check if string 0 to i is palindrome.         if (isPalin[0][i]) {              // if palindrome then cuts required is 0             dp[i] = 0;         } else {             for (let j = i; j >= 1; j--) {                  // if substring s[j...i] is palindromic                 // then we can make a cut over here                 if (isPalin[j][i]) {                      // update dp[i] with minimum cuts                     dp[i] = Math.min(dp[i], 1 + dp[j - 1]);                 }             }         }     }      // Return the minimum cuts required      // for the entire string 's'     return dp[n - 1]; }  // Driver Code  let s = "geek"; console.log(palPartition(s)); 

Output
2 


Next Article
Palindrome pair in an array of words (or strings)
author
kartik
Improve
Article Tags :
  • DSA
  • Dynamic Programming
  • Strings
  • Amazon
  • palindrome
Practice Tags :
  • Amazon
  • Dynamic Programming
  • palindrome
  • Strings

Similar Reads

  • Palindrome String Coding Problems
    A string is called a palindrome if the reverse of the string is the same as the original one. Example: “madam”, “racecar”, “12321”. Properties of a Palindrome String:A palindrome string has some properties which are mentioned below: A palindrome string has a symmetric structure which means that the
    2 min read
  • Palindrome String
    Given a string s, the task is to check if it is palindrome or not. Example: Input: s = "abba"Output: 1Explanation: s is a palindrome Input: s = "abc" Output: 0Explanation: s is not a palindrome Using Two-Pointers - O(n) time and O(1) spaceThe idea is to keep two pointers, one at the beginning (left)
    14 min read
  • Check Palindrome by Different Language

    • Palindrome Number Program in C
      Write a C program to check whether a given number is a palindrome or not. Palindrome numbers are those numbers which after reversing the digits equals the original number. Examples Input: 121Output: YesExplanation: The number 121 remains the same when its digits are reversed. Input: 123Output: NoExp
      4 min read

    • C Program to Check for Palindrome String
      A string is said to be palindrome if the reverse of the string is the same as the string. In this article, we will learn how to check whether the given string is palindrome or not using C program. The simplest method to check for palindrome string is to reverse the given string and store it in a tem
      4 min read

    • C++ Program to Check if a Given String is Palindrome or Not
      A string is said to be palindrome if the reverse of the string is the same as the original string. In this article, we will check whether the given string is palindrome or not in C++. Examples Input: str = "ABCDCBA"Output: "ABCDCBA" is palindromeExplanation: Reverse of the string str is "ABCDCBA". S
      4 min read

    • Java Program to Check Whether a String is a Palindrome
      A string in Java can be called a palindrome if we read it from forward or backward, it appears the same or in other words, we can say if we reverse a string and it is identical to the original string for example we have a string s = "jahaj " and when we reverse it s = "jahaj"(reversed) so they look
      8 min read

    Easy Problems on Palindrome

    • Sentence Palindrome
      Given a sentence s, the task is to check if it is a palindrome sentence or not. A palindrome sentence is a sequence of characters, such as a word, phrase, or series of symbols, that reads the same backward as forward after converting all uppercase letters to lowercase and removing all non-alphanumer
      9 min read
    • Check if actual binary representation of a number is palindrome
      Given a non-negative integer n. The problem is to check if binary representation of n is palindrome or not. Note that the actual binary representation of the number is being considered for palindrome checking, no leading 0’s are being considered. Examples : Input : 9 Output : Yes (9)10 = (1001)2 Inp
      6 min read
    • Print longest palindrome word in a sentence
      Given a string str, the task is to print longest palindrome word present in the string str.Examples: Input : Madam Arora teaches Malayalam Output: Malayalam Explanation: The string contains three palindrome words (i.e., Madam, Arora, Malayalam) but the length of Malayalam is greater than the other t
      14 min read
    • Count palindrome words in a sentence
      Given a string str and the task is to count palindrome words present in the string str. Examples: Input : Madam Arora teaches malayalam Output : 3 The string contains three palindrome words (i.e., Madam, Arora, malayalam) so the count is three. Input : Nitin speaks malayalam Output : 2 The string co
      5 min read
    • Check if characters of a given string can be rearranged to form a palindrome
      Given a string, Check if the characters of the given string can be rearranged to form a palindrome. For example characters of "geeksogeeks" can be rearranged to form a palindrome "geeksoskeeg", but characters of "geeksforgeeks" cannot be rearranged to form a palindrome. Recommended PracticeAnagram P
      14 min read
    • Lexicographically first palindromic string
      Rearrange the characters of the given string to form a lexicographically first palindromic string. If no such string exists display message "no palindromic string". Examples: Input : malayalam Output : aalmymlaa Input : apple Output : no palindromic string Simple Approach: 1. Sort the string charact
      13 min read
    geeksforgeeks-footer-logo
    Corporate & Communications Address:
    A-143, 7th Floor, Sovereign Corporate Tower, Sector- 136, Noida, Uttar Pradesh (201305)
    Registered Address:
    K 061, Tower K, Gulshan Vivante Apartment, Sector 137, Noida, Gautam Buddh Nagar, Uttar Pradesh, 201305
    GFG App on Play Store GFG App on App Store
    Advertise with us
    • Company
    • About Us
    • Legal
    • Privacy Policy
    • In Media
    • Contact Us
    • Advertise with us
    • GFG Corporate Solution
    • Placement Training Program
    • Languages
    • Python
    • Java
    • C++
    • PHP
    • GoLang
    • SQL
    • R Language
    • Android Tutorial
    • Tutorials Archive
    • DSA
    • Data Structures
    • Algorithms
    • DSA for Beginners
    • Basic DSA Problems
    • DSA Roadmap
    • Top 100 DSA Interview Problems
    • DSA Roadmap by Sandeep Jain
    • All Cheat Sheets
    • Data Science & ML
    • Data Science With Python
    • Data Science For Beginner
    • Machine Learning
    • ML Maths
    • Data Visualisation
    • Pandas
    • NumPy
    • NLP
    • Deep Learning
    • Web Technologies
    • HTML
    • CSS
    • JavaScript
    • TypeScript
    • ReactJS
    • NextJS
    • Bootstrap
    • Web Design
    • Python Tutorial
    • Python Programming Examples
    • Python Projects
    • Python Tkinter
    • Python Web Scraping
    • OpenCV Tutorial
    • Python Interview Question
    • Django
    • Computer Science
    • Operating Systems
    • Computer Network
    • Database Management System
    • Software Engineering
    • Digital Logic Design
    • Engineering Maths
    • Software Development
    • Software Testing
    • DevOps
    • Git
    • Linux
    • AWS
    • Docker
    • Kubernetes
    • Azure
    • GCP
    • DevOps Roadmap
    • System Design
    • High Level Design
    • Low Level Design
    • UML Diagrams
    • Interview Guide
    • Design Patterns
    • OOAD
    • System Design Bootcamp
    • Interview Questions
    • Inteview Preparation
    • Competitive Programming
    • Top DS or Algo for CP
    • Company-Wise Recruitment Process
    • Company-Wise Preparation
    • Aptitude Preparation
    • Puzzles
    • School Subjects
    • Mathematics
    • Physics
    • Chemistry
    • Biology
    • Social Science
    • English Grammar
    • Commerce
    • World GK
    • GeeksforGeeks Videos
    • DSA
    • Python
    • Java
    • C++
    • Web Development
    • Data Science
    • CS Subjects
    @GeeksforGeeks, Sanchhaya Education Private Limited, All rights reserved
    We use cookies to ensure you have the best browsing experience on our website. By using our site, you acknowledge that you have read and understood our Cookie Policy & Privacy Policy
    Lightbox
    Improvement
    Suggest Changes
    Help us improve. Share your suggestions to enhance the article. Contribute your expertise and make a difference in the GeeksforGeeks portal.
    geeksforgeeks-suggest-icon
    Create Improvement
    Enhance the article with your expertise. Contribute to the GeeksforGeeks community and help create better learning resources for all.
    geeksforgeeks-improvement-icon
    Suggest Changes
    min 4 words, max Words Limit:1000

    Thank You!

    Your suggestions are valuable to us.

    What kind of Experience do you want to share?

    Interview Experiences
    Admission Experiences
    Career Journeys
    Work Experiences
    Campus Experiences
    Competitive Exam Experiences