Problem:
正方形探索

縦に n 行、横に n 列並べられた、合計 n × n のマス目があります。いくつかのマス目には印がついています。各マス目の印の状態を読み込み、印のついていないマス目だけからなる最大の正方形の辺の長さを出力として表示するプログラムを作成してください。

たとえば各データセットで以下のようなデータが与えられます。

10
...*....**
..........
**....**..
........*.
..*.......
..........
.*........
..........
....*..***
.*....*...

入力データの一行が、一行のマス目を表現します。入力データの文字列のうち、.（ピリオド）は印のついていないマス目、*（アスタリスク）は印のついているマス目を示しています。

上記の例では、下図の 0 で示される正方形が最大となります。

...*....**
..........
**....**..
...00000*.
..*00000..
...00000..
.*.00000..
...00000..
....*..***
.*....*...

よって、5 と出力すれば正解になります。

なお、すべてのマス目に印がついている場合には、0 を出力してください。

Input

上記形式で複数のデータセットが与えられます。
n が 0 のとき入力の最後とします。n は 1000 以下とします。入力データの文字列には、ピリオド、アスタリスク、改行以外の文字は含まれません。データセットの数は 50 を超えません。

Output

各データセットに対し、最大の正方形の辺の長さ（整数）を１行に出力して下さい。

Sample Input

10
...*....**
..........
**....**..
........*.
..*.......
..........
.*........
..........
....*..***
.*....*...
10
****.*****
*..*.*....
****.*....
*....*....
*....*****
..........
****.*****
*..*...*..
****...*..
*..*...*..
0

Output for the Sample Input

5
3

Solution in JAVA (judge verdict: Accepted)

import java.util.*;
import java.io.*;

class Main {

    public static void main(String[] args) {

	final Scanner stdin = new Scanner(System.in);

	while ( true ) {
	    final int size = Integer.parseInt( stdin.nextLine() );

	    if ( size == 0 ) {
		break;
	    }

	    final char[][] map = new char[size][];
	    
	    for ( int i = 0; i < size; i++ ) {
		map[i] = stdin.nextLine().toCharArray(); 
	    }

	    final int[][] acCol = new int[size][size];
	    for ( int r = 0; r < size; r++ ) {
		acCol[0][r] = ( map[0][r] == '.' ) ? 1 : 0;
		for ( int c = 1; c < size; c++ ) {
		    if ( map[c][r] == '.' ) {
			acCol[c][r] = acCol[c - 1][r] + 1;
		    } else {
			acCol[c][r] = 0;	
		    }
		}
	    }

	    final int[][] acRow = new int[size][size];
	    for ( int c = 0; c < size; c++ ) {
		acRow[c][0] = ( map[c][0] == '.' ) ? 1 : 0;
		for ( int r = 1; r < size; r++ ) {
		    if ( map[c][r] == '.' ) {
			acRow[c][r] = acRow[c][r - 1] + 1;
		    } else {
			acRow[c][r] = 0;	
		    }
		}
	    }

	    final int[][] ans = new int[size][size];
	    for ( int i = 0; i < size; i++ ) {
		ans[i][0] = ( map[i][0] == '.' ? 1 : 0 );
		ans[0][i] = ( map[0][i] == '.' ? 1 : 0 );
	    }
	    
	    int maxSize = 0;
	    for ( int c = 1; c < size; c++ ) {
		for ( int r = 1; r < size; r++ ) {
		    if ( map[c][r] == '*' ) {
			ans[c][r] = 0;
		    } else {
			if ( acRow[c][r] > ans[c - 1][r - 1] + 1 && acCol[c][r] > ans[c - 1][r - 1] + 1 ) {
			    ans[c][r] = ans[c - 1][r - 1] + 1;
			} else {
			    ans[c][r] = Math.min( acRow[c][r], acCol[c][r] );
			}
			maxSize = Math.max( maxSize, ans[c][r] );
		    }
		}
	    }
	    System.out.println( maxSize );
	}
    }
}