Palindrome Partitioning II
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.
Analysis
核心:
- cut[i] 代表s的前i个字母至少需要cut多少次
 - scan s,从某一个位置i的左右开始去找。当找到一个palindrome的时候,更新cut的值为前面不是palindrome的部分cut值+1,因为前面的已经算好,加上一个palindrome,多cut一次即可
 - 最后返回cut[s.length]
 
Example: "aabbabc", return 3, aa | b | bab | c
        0   1   2   3   4   5   6   
        a   a   b   b   a   b   c
    -1  0   0   1   1   1   2   3
Initialize cut = [-1  0   1   2   3   4   5   6]
i=0: 
odd: "a" is palindrome, update cut[1] to min(0, -1+1)
even: "aa" is palindrome, update cut[2] to min(1, -1+1)
cut = [-1  0   0   2   3   4   5   6]
i=1:
odd: "a" is palindrome, update cut[2] to min(0, 0+1)
even: no palindrome
cut = [-1  0   0   2   3   4   5   6]
i=2:
odd: "b" is palindrome, update cut[3] to min(2, 0+1)
even: "bb" is palindrome, update cut[4] to min(3, 0+1)
      "abba" is palindrome, update cut[5] to min(4, 0+1)
cut = [-1  0   0   1   1   1   5   6]
i=3:
odd: "b" is palindrome, update cut[4] to min(1, 1+1)
even: no palindrome
cut = [-1  0   0   1   1   1   5   6]
i=4:
odd: "a" is palindrome, update cut[5] to min(1, 1+1)
even: "bab" is palindrome, update cut[6] to min(5, 1+1)
cut = [-1  0   0   1   1   1   2   6]
i=5:
odd: "b" is palindrome, update cut[6] to min(2, 1+1)
even: no palindrome
cut = [-1  0   0   1   1   1   2   6]
i=6:
odd: "c" is palindrome, update cut[7] to min(6, 2+1)
even: no palindrome
cut = [-1  0   0   1   1   1   2   3]
return cut[7]=3
Code
public class Solution {
    public int minCut(String s) {
        if (s==null || s.length()<=1) return 0;
        int len = s.length();
        //cut[i]: number of cuts for the first i chars
        int[] cut = new int[len+1];
        //initialize with maximum possible cuts (cut to single chars)
        for (int i=0; i<=len; i++) cut[i]=i-1;
        for (int i=0; i<len; i++){
            //odd length palindrome
            for (int j=0; i-j>=0 && i+j <len && s.charAt(i-j)==s.charAt(i+j); j++){
                cut[i+j+1] = Math.min(cut[i+j+1], 1+cut[i-j]);
            }
            //even length palindrome
            for (int j=1; i-j+1>=0 && i+j <len && s.charAt(i-j+1)==s.charAt(i+j); j++){
                cut[i+j+1] = Math.min(cut[i+j+1], 1+cut[i-j+1]);
            }
        }
        return cut[len];
    }
}