UVA - 10010 - Where's Waldorf? 

This article will explain my thought process to solve a problem called Where's Waldorf? (PDF) from UVA Online Judge. Read the original problem statement before reading this article.

Keywords: String Matching, Grid

Objective 

Given:

  1. Grid of letters.

  2. List of words.

We want to:

  1. Find the position of each word.

Glossary 

  1. String Matching — A process of finding a smaller string inside a larger text.

  2. Grid — A two-dimensional array mostly used in mathematical and scientific calculations.

Observation 

We want to find a string within a grid, with 8 possible orientations: (1) up, (2) up-right, (3) right, (4) down-right, (5) down, (6) down-left, (7) left, and (8) up-left. Since the size of the grid is quiet small, it is possible to scan through every cells within the grid.

From each cells, we can try to reconstruct a string with the same length on the 8 possible orientations. If the reconstructed string is identical to the word, then the starting cell is the word position.

Since we want to prioritize (1) up-most position and (2) left-most position, we must process the cells starting from the up-to-down row and left-to-right column.

Algorithm 

The grid scan can be implemented using nested loop, with the first loop being the row and the second loop being the column. Don’t forget to ignore the upper/lower case when comparing the reconstructed string against the word.

The time complexity of this solution is O({total words} * {grid length}^3) or O(10^6).

Implementation 

import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.PrintWriter; import java.util.Scanner; /** * 10010 - Where's Waldorf? * Time limit: 3.000 seconds * https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=24&page=show_problem&problem=951 */ public class Main { public static void main(final String... args) { final Scanner in = new Scanner(new BufferedInputStream(System.in)); final PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out)); final Process process = new Process(); final int totalCases = in.nextInt(); for (int i = 0; i < totalCases; i++) { final Input input = new Input(); input.totalRows = in.nextInt(); input.totalColumns = in.nextInt(); input.grid = new char[input.totalRows][]; for (int j = 0; j < input.totalRows; j++) { input.grid[j] = in.next().toCharArray(); } input.totalWords = in.nextInt(); input.words = new String[input.totalWords]; for (int j = 0; j < input.totalWords; j++) { input.words[j] = in.next(); } final Output output = process.process(input); if (i > 0) out.println(); for (final int[] cell : output.cells) { out.format("%d %d\n", cell[0], cell[1]); } } in.close(); out.flush(); out.close(); } } class Input { public int totalRows; public int totalColumns; public char[][] grid; public int totalWords; public String[] words; } class Output { public int[][] cells; } class Process { public Output process(final Input input) { final Output output = new Output(); output.cells = new int[input.totalWords][]; for (int i = 0; i < input.totalWords; i++) { final String word = input.words[i]; output.cells[i] = findFirst(input.grid, word); } return output; } private int[] findFirst( final char[][] grid, final String word ) { for (int row = 0; row < grid.length; row++) { for (int column = 0; column < grid[0].length; column++) { if (contains(grid, row, column, word)) { return new int[]{row + 1, column + 1}; } } } return null; } private boolean contains( final char[][] grid, final int row, final int column, final String word ) { for (int rowStep = -1; rowStep <= 1; rowStep++) { for (int columnStep = -1; columnStep <= 1; columnStep++) { if (rowStep == 0 && columnStep == 0) continue; final String gridWord = read(grid, row, column, rowStep, columnStep, word.length()); if (word.equalsIgnoreCase(gridWord)) return true; } } return false; } private String read( final char[][] grid, final int startRow, final int startColumn, final int rowStep, final int columnStep, final int length ) { final StringBuilder word = new StringBuilder(); for ( int row = startRow, column = startColumn; 0 <= row && row < grid.length && 0 <= column && column < grid[0].length && word.length() < length; row += rowStep, column += columnStep ) { word.append(grid[row][column]); } return word.toString(); } }


Powered by Docmost