package main
import (
"fmt"
)
func main() {
row := 0
for {
n, _ := fmt.Scan(&row)
col := row
if n == 0 {
break
} else {
arr := make([][]int, row)
for i:=0; i<row; i++ {
arr[i] = make([]int, col)
for j:=0; j<col; j++ {
fmt.Scan(&arr[i][j])
}
}
right := make([][]int, row)
down := make([][]int, row)
for i:=0; i<row; i++ {
right[i] = make([]int, col)
down[i] = make([]int, col)
}
// 构建右矩阵,arr[i][j] 代表i,j从右往左连续1的个数(1构建的边长)
for i:=row-1; i>=0; i-- {
for j:=col-1; j>=0; j-- {
if arr[i][j] == 1 {
if j+1 < col {
right[i][j] = right[i][j+1] + 1
} else {
right[i][j] = 1
}
}
}
}
// 构建下矩阵,arr[i][j] 代表i,j从上往下连续1的个数(1构建的边长)
for j:=0; j<col; j++ {
for i:=row-1; i>=0; i-- {
if arr[i][j] == 1 {
if i+1 < row {
down[i][j] = down[i+1][j] + 1
} else {
down[i][j] = 1
}
}
}
}
maxl := 0
for i:=0; i<row; i++ {
for j:=0; j<col; j++ {
if arr[i][j] == 1 { // 当前为1这个点时开始判断正方形最大边长
// 边长为1时-(边长可取的最大值min(col-j, row-i))范围内查找是否满足正方形
for board := 1; board <= min(col-j, row-i); board++ {
// i,j 这个点 right[i][j] 代表i,j这个点(从左往右的边长)边长大于需要的board
// i,j 这个点 down[i][j] 代表i,j这个点(从上往下的边长)边长大于需要的board
if right[i][j] >= board &&
down[i][j] >= board {
// 此时只需要判断[i+board-1,j] 这个点从左往右的边长, right[i+board-1][j]边长大于需要的board
// 此时只需要判断[i,j+board-1] 这个点从上往下的点边长
// down[i][j+board-1]大于需要的board
// 都满足则认为找到最大边长,更新最大值
if i+board-1 < row && j+board-1 < col {
if right[i+board-1][j] >=board && down[i][j+board-1] >= board {
maxl = max(maxl, board)
}
}
}
}
}
}
}
fmt.Println(maxl)
}
}
}
func min(a, b int) int {
if a<b {
return a
}
return b
}
func max(a, b int) int {
if a>b {
return a
}
return b
}