Given a string, find the minimum cuts needed to partition it such that each partition is a palindrome.

For example,

  1. BABABCBADCD – The minimum cuts required are 2 as BAB|ABCBA|DCD.
  2. ABCBA – The minimum cuts required are 0 as ABCBA is already a palindrome.
  3. ABCD – The minimum cuts required are 3 as A|B|C|D.

Practice this problem

We can break the problem into a set of related subproblems that partition the given string to yield the lowest total cuts. Following is the recursive algorithm to find the minimum cuts:

  1. Separate the given string into two subsequences.
  2. Recursively find the minimum cuts required in each subsequence.
  3. Do this for each possible position at which the string can be cut, and take the minimum over all of them.

For example, if we have string ABCB, compute the cuts required to find each of A|BCB, AB|CB, and ABC|B, making recursive calls to find the minimum cuts to compute BCB, AB, CB, and ABC to choose the best one.

Following is the C++, Java, and Python implementation of the idea:

C++


Download  Run Code

Output:

The minimum cuts required are 2

Java


Download  Run Code

Output:

The minimum cuts required are 2

Python


Download  Run Code

Output:

The minimum cuts required are 2

The time complexity of the above solution is exponential and occupies space in the call stack.

 
The problem has an optimal substructure and also exhibits overlapping subproblems. If we draw the solution’s recursion tree, we can see that the same subproblems are repeatedly computed. Since both optimal substructure and overlapping subproblems properties of dynamic programming are satisfied, we can save subproblem solutions in memory rather than computed them repeatedly.

We can further optimize the above recursive solution by removing the isPalindrome() function, which takes linear time in the worst case. Instead, the idea is to preprocess the string and maintain a lookup table to check if the substring starting at index i and ending at index j is a palindrome or not in constant time. This is demonstrated below in C++, Java, and Python:

C++


Download  Run Code

Output:

The minimum cuts required are 2

Java


Download  Run Code

Output:

The minimum cuts required are 2

Python


Download  Run Code

Output:

The minimum cuts required are 2

The time complexity of the above top-down solution is O(n3) and requires O(n2) extra space, where n is the length of the input string.

 
We can also solve this problem in a bottom-up manner. In the bottom-up approach, we solve smaller subproblems first, then solve larger subproblems from them. It has the “less” asymptotic runtime and requires no recursion. The approach is demonstrated below in C++, Java, and Python:

C++


Download  Run Code

Output:

The minimum cuts required are 4

Java


Download  Run Code

Output:

The minimum cuts required are 4

Python


Download  Run Code

Output:

The minimum cuts required are 4

The time complexity of the above bottom-up solution is O(n2) and requires O(n2) extra space, where n is the length of the input string.