# [LeetCode 132] Palindrome Partitioning II

### Question

Given a string s, partition s such that every substring of the partition is a palindrome.

Return the minimum cuts needed for a palindrome partitioning of s.

For example, given s = `"aab"`,
Return `1` since the palindrome partitioning `["aa","b"]` could be produced using 1 cut.

### Stats

 Frequency 3 Difficulty 4 Adjusted Difficulty 5 Time to use --------

Ratings/Color = 1(white) 2(lime) 3(yellow) 4/5(red)

### Analysis

This is DP, but not traditional DP question

#### IT IS DOUBLE DP!

It is very hard for me to even understand the solution, but I have found a great analysis from peking2’s blog.

dp(i) = min( 1+dp(j+1), if substring(i,j) is palindrome)

dp(i)(j)=true if s(i)==s(j) && dp(i+1)(j-1)

A more detailed analysis is available in this blog.

[Thoughts]

D[i,n] = 区间[i,n]之间最小的cut数，n为字符串长度

a   b   a   b   b   b   a   b   b   a   b   a
i                                  n

a   b   a   b   b   b   a   b   b   a   b   a
i                   j  j+1    n

D[i] = 区间[i,n]之间最小的cut数，n为字符串长度， 则,

D[i] = min(1+D[j+1] )    i<=j <n

P[i][j] = true if [i,j]为回文

P[i][j] = str[i] == str[j] && P[i+1][j-1];

### Solution

The coding is not easy, especially when 2 DP are written in 1 for-loop.

I wrote many times until I finally achieved the nice and concise solution that you see below.

### Code

Doing everything in 1 loop, not an intuitive code.

``````public int minCut(String s) {
int len = s.length();
if (len <= 1) return 0;
boolean[][] pl = new boolean[len][len];
int[] dp = new int[len];
for (int i = len-1; i >= 0; i --) {
dp[i] = Integer.MAX_VALUE;
for (int j = i; j < len; j ++) {
// first set pl[][], then update dp[i]
if (j - i <= 1) pl[i][j] = s.charAt(i) == s.charAt(j);
else pl[i][j] = s.charAt(i) == s.charAt(j) & pl[i+1][j-1];
if (pl[i][j]) {
if (j == len-1) dp[i] = 0;
else
dp[i] = Math.min(dp[i], dp[j+1] + 1);
}
}
}
return dp[0];
}
``````

Updated on July 18th, 2014, written by me.

``````boolean[][] map = null;

public int minCut(String s) {
if (s == null || s.length() == 0) {
return 0;
}
map = getMap(s);
int len = s.length();
int[] dp = new int[len + 1];
dp[0] = -1;
for (int i = 0; i < len; i++) {
dp[i+1] = Integer.MAX_VALUE;
for (int j = 0; j <= i; j++) {
if (map[j][i]) {
dp[i+1] = Math.min(dp[i+1], dp[j] + 1);
}
}
}
return dp[len];
}

private boolean[][] getMap(String s) {
int len = s.length();
boolean[][] map = new boolean[len][len];
for (int i = len - 1; i >= 0; i--) {
for (int j = 0; j < len; j++) {
if (i > j) {
continue;
} else if (i == j) {
map[i][j] = true;
} else {
if (i + 1 == j) {
map[i][j] = s.charAt(i) == s.charAt(j);
} else {
map[i][j] = s.charAt(i) == s.charAt(j) && map[i+1][j-1];
}
}
}
}
return map;
}
``````