BoggleSolver.java
package cn.denghanxi.assignment.s53;
import java.util.HashSet;
import java.util.Set;
/**
* 注意,所有字典必须为大写!!! 因为 Node 是为了性能的实现。
*/
public class BoggleSolver {
// private Map<String, Boolean> dic;
private Set<String> result;
private boolean[][] marked;
private StringBuilder stringBuilder = new StringBuilder();
private Node root;
// Initializes the data structure using the given array of strings as the dictionary.
// (You can assume each word in the dictionary contains only the uppercase letters A through Z.)
public BoggleSolver(String[] dictionary) {
root = new Node();
for (String s : dictionary) {
if (s.length() > 0) {
setupNode(root, s, 0);
}
}
}
private void setupNode(Node root, String s, int i) {
if (root.getNext(s.charAt(i)) == null) {
root.put(s.charAt(i), new Node());
}
if (i + 1 < s.length()) {
setupNode(root.getNext(s.charAt(i)), s, i + 1);
}
if (i + 1 == s.length()) {
root.getNext(s.charAt(i)).setWord(true);
}
}
// Returns the set of all valid words in the given Boggle board, as an Iterable.
public Iterable<String> getAllValidWords(BoggleBoard board) {
result = new HashSet<>();
marked = new boolean[board.rows()][board.cols()];
for (int i = 0; i < board.rows(); i++) {
for (int j = 0; j < board.cols(); j++) {
crawl(board, i, j, stringBuilder, root);
}
}
return result;
}
private void crawl(BoggleBoard board, int row, int col, StringBuilder stringBuilder, Node node) {
char c = board.getLetter(row, col);
stringBuilder.append((c == 'q' || c == 'Q') ? "QU" : c);
Node nextNode = nextNode(node, c);
if (nextNode == null) {
if (c == 'q' || c == 'Q') {
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
}
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
return;
}
//checkIfAWord(stringBuilder);
if (stringBuilder.length() > 2) {
if (nextNode.isWord()) {
result.add(stringBuilder.toString());
}
}
marked[row][col] = true;
//go on
//-1 0
if (row - 1 >= 0 && !marked[row - 1][col]) {
crawl(board, row - 1, col, stringBuilder, nextNode);
}
//-1 +1
if (row - 1 >= 0 && col + 1 < board.cols() && !marked[row - 1][col + 1]) {
crawl(board, row - 1, col + 1, stringBuilder, nextNode);
}
//0 +1
if (col + 1 < board.cols() && !marked[row][col + 1]) {
crawl(board, row, col + 1, stringBuilder, nextNode);
}
//+1 +1
if (row + 1 < board.rows() && col + 1 < board.cols() && !marked[row + 1][col + 1]) {
crawl(board, row + 1, col + 1, stringBuilder, nextNode);
}
//+1 0
if (row + 1 < board.rows() && !marked[row + 1][col]) {
crawl(board, row + 1, col, stringBuilder, nextNode);
}
//+1 -1
if (row + 1 < board.rows() && col - 1 >= 0 && !marked[row + 1][col - 1]) {
crawl(board, row + 1, col - 1, stringBuilder, nextNode);
}
//0 -1
if (col - 1 >= 0 && !marked[row][col - 1]) {
crawl(board, row, col - 1, stringBuilder, nextNode);
}
//-1 -1
if (row - 1 >= 0 && col - 1 >= 0 && !marked[row - 1][col - 1]) {
crawl(board, row - 1, col - 1, stringBuilder, nextNode);
}
marked[row][col] = false;
if (c == 'q' || c == 'Q') {
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
}
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
}
private Node nextNode(Node node, char nextChar) {
if (nextChar == 'q' || nextChar == 'Q') {
if (node.getNext(nextChar) == null) return null;
return node.getNext(nextChar).getNext('U');
}
return node.getNext(nextChar);
}
// Returns the score of the given word if it is in the dictionary, zero otherwise.
// (You can assume the word contains only the uppercase letters A through Z.)
public int scoreOf(String word) {
Node node = root;
for (char c : word.toCharArray()) {
node = node.getNext(c);
if (node == null) return 0;
}
if (!node.isWord) return 0;
switch (word.length()) {
case 0:
case 1:
case 2:
return 0;
case 3:
case 4:
return 1;
case 5:
return 2;
case 6:
return 3;
case 7:
return 5;
default:
return 11;
}
}
// R-way trie node
private static class Node {
private boolean isWord = false;
private Node[] next;
public boolean isWord() {
return isWord;
}
public void setWord(boolean word) {
isWord = word;
}
void put(char index, Node node) {
if (next == null) {
next = new Node[26];
}
next[index - 65] = node;
}
Node getNext(char c) {
if (next == null) return null;
return next[c - 65];
}
}
}