纵横找单词【2014年雅虎研究院校园招聘笔试题目之一】

来源:互联网 发布:em算法 高斯混合模型 编辑:程序博客网 时间:2024/04/27 23:44

一、背景介绍

    纵横找单词的输入是一个二维的字符数组和一个单词列表,目的是找出网格中的单词,这些单词可能在水平方向、垂直方向或在任何对角线上。例如,在下面的网格中包含单词:this、two、fat和that。单词this始于第0行,第0列,即点(0,0)一直到(3,0);two从(0,0)到(2,0);fat从(3,0)到(1,2);that从(3,3)到(0,0)。


01230this1wats2oahg3fgdt

    PS. 该算法是2014年雅虎研究院校园招聘的一道算法题,原题是从表格中找到YAHOO!单词的位置,与该算法雷同。


二、解决思路

    假设在某一方向搜索,找到字符序列qx,网格中没有任何以qx开头的单词,此时没有必要继续在最内侧循环查找,应该立即分析另一个方向。

    伪代码如下:

for each row R        for each column C            for each direction D                for each word length L                    check if L chars starting at row R column                    C in direction D form a word                    if they do not form a prefix,                        break;
    如何确定单词的前缀呢?可以采用集合类中的binarySearch方法,该方法要么返回匹配的索引,要么返回至少与目标一样大的最小元素的位置(作为负数)。


三、程序实现

public class WordSearch {private int rows;private int columns;private char theBoard[][];private String[] theWords;private BufferedReader puzzleStream;private BufferedReader wordStream;private BufferedReader in = new BufferedReader(new InputStreamReader(System.in));public WordSearch() throws IOException {puzzleStream = openFile("D:\\puzzle.txt");wordStream = openFile("D:\\dictionary.txt");System.out.println("Reading files...");readPuzzle();readWords();}/** * @throws IOException *  */private void readWords() throws IOException {List<String> words = new ArrayList<String>();String lastWord = null;String thisWord;while ((thisWord = wordStream.readLine()) != null) {if (lastWord != null && thisWord.compareTo(lastWord) < 0) {System.out.println("Dictionary is not sorted... skipping");continue;}words.add(thisWord);lastWord = thisWord;}theWords = new String[words.size()];theWords = words.toArray(theWords);}/** * @throws IOException *  */private void readPuzzle() throws IOException {String oneLine;List<String> puzzleLines = new ArrayList<String>();if ((oneLine = puzzleStream.readLine()) == null)throw new IOException("No lines in puzzle file");columns = oneLine.length();puzzleLines.add(oneLine);while ((oneLine = puzzleStream.readLine()) != null) {if (oneLine.length() != columns)System.err.println("Puzzle is not rectangular; skipping row");elsepuzzleLines.add(oneLine);}rows = puzzleLines.size();theBoard = new char[rows][columns];int r = 0;for (String theLine : puzzleLines)theBoard[r++] = theLine.toCharArray();}/** * @param string * @return */private BufferedReader openFile(String message) {String fileName = message;FileReader thefile;BufferedReader fileIn = null;do {System.out.println(message + ": ");try {if (fileName == null)System.exit(0);thefile = new FileReader(fileName);fileIn = new BufferedReader(thefile);} catch (FileNotFoundException e) {System.err.println("Cannot open " + fileName);}} while (fileIn == null);System.out.println("Opened " + fileName);return fileIn;}public int solvePuzzle() {int matches = 0;for (int r = 0; r < rows; r++)for (int c = 0; c < columns; c++)for (int rd = -1; rd <= 1; rd++)for (int cd = -1; cd <= 1; cd++)matches += solveDirection(r, c, rd, cd);return matches;}/** * @param r * @param c * @param rd * @param cd * @return */private int solveDirection(int baseRow, int baseCol, int rowDelta, int colDelta) {String charSequence = "";int numMatches = 0;int searchResult;charSequence += theBoard[baseRow][baseCol];for (int i = baseRow + rowDelta, j = baseCol + colDelta; i >= 0&& j >= 0 && i < rows && j < columns; i += rowDelta, j += colDelta) {charSequence += theBoard[i][j];searchResult = prefixSearch(theWords, charSequence);if(searchResult == theWords.length)break;if(!theWords[searchResult].startsWith(charSequence))break;if(theWords[searchResult].equals(charSequence)){numMatches++;System.out.println("Found " + charSequence + " at " + baseRow + " " + baseCol + " to " + i + " " + j);}}return numMatches;}/** * @param theWords2 * @param charSequence * @return */private int prefixSearch(String[] a, String x) {int idx = Arrays.binarySearch(a, x);if(idx<0)return -idx-1;else return idx;}public static void main(String[] args){WordSearch p = null;try{p = new WordSearch();}catch(IOException e){System.out.println("IO Error:");e.printStackTrace();return;}System.out.println("Solving ...");System.out.println(p.solvePuzzle());}}