public int numDistinct(String S, String T) {

    // each string starts at position 1 and ends at length
    int[][] dpTable = new int[S.length() + 1][T.length() + 1];

    for (int i = 0 ; i <= S.length() ; i++) {
      // at position 0 of S, all equals to 0, default value
      // at position 0 of T, all equals to 1, override position 0,0
      dpTable[i][0] = 1;
    }

    // this is a O(M*N) solution with M*N space
    // cab by future optimized to N space
    for (int i = 1 ; i <= S.length() ; i++) {
      for (int j = 1 ; j <= T.length() ; j++) {
        if (S.charAt(i - 1) == T.charAt(j - 1)) {
          dpTable[i][j] = dpTable[i - 1][j - 1] + dpTable[i - 1][j];
        } else {
          dpTable[i][j] = dpTable[i - 1][j];
        }
      }
    }

    return dpTable[S.length()][T.length()];
  }