public int minCut(String s){
  if (s == null || s.length() == 0)   return 0;
  int len=s.length();
  boolean[][] p=new boolean[len][len];
  for (int i=0; i < len; i++)   Arrays.fill(p[i],false);
  int[] results=new int[len];
  for (int start=len - 1; start >= 0; start--) {
    results[start]=len - start - 1;
    for (int end=start; end < len; end++) {
      if (s.charAt(start) == s.charAt(end)) {
        if (end - start < 2)         p[start][end]=true;
 else         p[start][end]=p[start + 1][end - 1];
      }
      if (p[start][end]) {
        if (end=len - 1)         results[start]=0;
 else         results[start]=Math.min(results[start],results[end + 1] + 1);
      }
    }
  }
  return results[0];
}

public int minCut ( String s ) { if ( s == null || s . length ( ) == 0 ) return 0 ; int len = s . length ( ) ; boolean [ ] [ ] p = new boolean [ len ] [ len ] ; for ( int i = 0 ; i < len ; i ++ ) Arrays . fill ( p [ i ] , false ) ; int [ ] results = new int [ len ] ; for ( int start = len - 1 ; start >= 0 ; start -- ) { results [ start ] = len - start - 1 ; for ( int end = start ; end < len ; end ++ ) { if ( s . charAt ( start ) == s . charAt ( end ) ) { if ( end - start < 2 ) p [ start ] [ end ] = true ; else p [ start ] [ end ] = p [ start + 1 ] [ end - 1 ] ; } if ( p [ start ] [ end ] ) { if ( end = len - 1 ) results [ start ] = 0 ; else results [ start ] = Math . min ( results [ start ] , results [ end + 1 ] + 1 ) ; } } } return results [ 0 ] ; }
calculate and maintain 2 dp states : pal [ i ] [ j ] , which is whether s [ i . . j ] forms a pal d [ i ] , which is the mincut for s [ i . . n - 1 ] once we comes to a pal [ i ] [ j ] = = true : if j = = n - 1 , the string s [ i . . n - 1 ] is a pal , mincut is 0 , d [ i ] = 0 ; else : the current cut num ( first cut s [ i . . j ] and then cut the rest s [ j + 1 . . . n - 1 ] ) is 1 + d [ j + 1 ] , compare it to the exisiting mincut num d [ i ] , repalce if smaller .
