Boggler Solver 在棋盘中寻找与字典中相吻合的字符,利用深度优先搜索配合剪枝,数据结构是R-way Tries,效果不错,Coursera在线评测98分~
import java.util.ArrayList;
import java.util.List;
import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.StdOut;
public class BoggleSolver
{ private int n = 0;
private int M,N;
private boolean Visited[][];
private class Node {
public int val= -1;
public Node[] next = new Node[26];
}
private Node root;
private Node nodeCache;
private Node put(Node x, String key, int val, int d) {
if (x == null) x = new Node();
if (d == key.length()) {
if (x.val == -1) n++;
x.val = val;
return x;
}
int c = key.charAt(d) - 'A';
x.next[c] = put(x.next[c], key, val, d+1);
return x;
}
private boolean prefixQuery(String string){
int m = string.length();
Node start = root;
for(int i = 0;i < m;i++){
if(start.next[string.charAt(i)-'A']!=null) start = start.next[string.charAt(i)-'A'];
else return false;
}
nodeCache = start;
return true;
}
// 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){
for(int i = 0;i<dictionary.length;i++){
root = put(root,dictionary[i],i,0);
}
}
// Returns the set of all valid words in the given Boggle board, as an Iterable.
public Iterable<String> getAllValidWords(BoggleBoard board){
List<String> results = new ArrayList<String>();
//String path = new String();
M = board.rows();
N = board.cols();
Visited = new boolean[M][N];
//Visited[0][0]=true;
for(int i = 0; i< M ;i++){
for(int j = 0;j < N;j++){
String path = new String();
path +=(board.getLetter(i, j)=='Q'?"QU":board.getLetter(i, j));
dfs(board,i,j,path,results);
}
}
return results;
}
private void dfs(BoggleBoard board,int i, int j,String path, List<String> results){
if(i < 0 || i > board.rows()-1 || j < 0 || j > board.cols()-1 ) return;
//StdOut.println(path.toString());
if(Visited[i][j] == true) return;
if(!prefixQuery(path)) return;
if(nodeCache.val!=-1&&path.length()>2){
//StdOut.println(path.toString());
if(!results.contains(path)){
//StdOut.println(path.toString());
results.add(path);
}
}
Visited[i][j]=true;
for(int rows = -1; rows < 2;rows++){
for(int cols = -1; cols < 2;cols++){
if(cols == 0 && rows == 0) continue;
if(i+rows > board.rows()-1 || i+rows < 0 || j + cols > board.cols()-1 || j + cols < 0){
continue;
}else{
//StdOut.println(path+board.getLetter(i+rows, j+cols));
dfs(board,i+rows,j+cols,path+(board.getLetter(i+rows, j+cols)=='Q'?"QU":board.getLetter(i+rows, j+cols)),results);
}
}
}
Visited[i][j]=false;
}
// 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){
if(!prefixQuery(word)) return 0;
if(nodeCache.val==-1) return 0;
int m = word.length();
switch(m){
case 0:
return 0;
case 1:
return 0;
case 2:
return 0;
case 3:
return 1;
case 4:
return 1;
case 5:
return 2;
case 6:
return 3;
case 7:
return 5;
default:
return 11;
}
}
public static void main(String[] args) {
In in = new In(args[0]);
String[] dictionary = in.readAllStrings();
BoggleSolver solver = new BoggleSolver(dictionary);
BoggleBoard board = new BoggleBoard(args[1]);
int score = 0;
for (String word : solver.getAllValidWords(board)) {
StdOut.println(word);
score += solver.scoreOf(word);
}
//StdOut.println("Score = " + );
StdOut.println("Score = " + score);
}
}