class Solution {
public int findMinStep(String board, String hand) {
Map<String, Integer> mem = new HashMap<>();
final int ans = dfs(board + '#', hand, mem);
return ans == Integer.MAX_VALUE ? -1 : ans;
}
private int dfs(String board, final String hand, Map<String, Integer> mem) {
final String hashKey = board + '#' + hand;
if (mem.containsKey(hashKey))
return mem.get(hashKey);
board = deDup(board);
if (board.equals("#"))
return 0;
Set<Character> boardSet = new HashSet<>();
for (final char c : board.toCharArray())
boardSet.add(c);
StringBuilder sb = new StringBuilder();
for (final char h : hand.toCharArray())
if (boardSet.contains(h))
sb.append(h);
final String hs = sb.toString();
if (sb.length() == 0) // infeasible
return Integer.MAX_VALUE;
int ans = Integer.MAX_VALUE;
for (int i = 0; i < board.length(); ++i)
for (int j = 0; j < hs.length(); ++j) {
// Place hs[j] in board[i].
final String newHand = hs.substring(0, j) + hs.substring(j + 1);
String newBoard = board.substring(0, i) + hs.charAt(j) + board.substring(i);
final int res = dfs(newBoard, newHand, mem);
if (res < Integer.MAX_VALUE)
ans = Math.min(ans, 1 + res);
}
mem.put(hashKey, ans);
return ans;
}
private String deDup(String board) {
int start = 0; // the start index of a color sequenece
for (int i = 0; i < board.length(); ++i)
if (board.charAt(i) != board.charAt(start)) {
if (i - start >= 3)
return deDup(board.substring(0, start) + board.substring(i));
start = i; // Meet a new sequence.
}
return board;
}
}