[String Table] Boggler Solver

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);
    }
}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值