Palindrome Partitioning: Minimum Cuts

hard Strings

Problem

Cut a string into pieces so that every piece is a palindrome (reads the same backwards). Print the smallest number of cuts needed. A string that is already a palindrome needs 0 cuts.

Constraints

  • 1 <= length <= 2000

Examples

Input

aab

Output

1

Input

abcd

Output

3

Solutions

Best approachTime O(n^2)Space O(n^2)

A table tells in O(1) whether any piece is a palindrome. Then a second table finds the best cut count for each prefix by trying every last piece. Total time and memory are O(n^2).

Same code works in Java810172125Basic features only, so nothing changes between versions.
/*
 * Problem : Fewest cuts.
 * Input   : One string.
 * Output  : The number of cuts.
 * Approach: Palindrome table + DP
 * Time    : O(n^2)
 * Space   : O(n^2)
 * Java    : 8 or newer.
 */
import java.util.Scanner;

public class Main {
    // This method solves the task. It receives the input and returns the answer.
    static long solve(String s) {
        int n = s.length();
        // Step 1: pal[i][j] says whether the piece from i to j is a palindrome. A piece is one if the ends match and the inside is one.
        boolean[][] pal = new boolean[n][n];
        for (int i = n - 1; i >= 0; i--) {
            for (int j = i; j < n; j++) {
                pal[i][j] = s.charAt(i) == s.charAt(j) && (j - i < 2 || pal[i + 1][j - 1]);
            }
        }
        // Step 2: cuts[j] is the minimum cuts for the first j + 1 letters.
        long[] cuts = new long[n];
        for (int j = 0; j < n; j++) {
            if (pal[0][j]) {
                cuts[j] = 0;
                continue;
            }
            // Step 3: Try the last piece from i to j. It adds one cut after the best answer for the letters before it.
            cuts[j] = j;
            for (int i = 1; i <= j; i++) {
                if (pal[i][j]) {
                    cuts[j] = Math.min(cuts[j], cuts[i - 1] + 1);
                }
            }
        }
        return cuts[n - 1];
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String s = scanner.hasNextLine() ? scanner.nextLine() : "";
        System.out.println(solve(s));
    }
}
Hints (2)
  1. Why is the palindrome table filled from the end?
  2. What is the largest answer for a string of n letters?