← Home
package main

import (
	"bufio"
	"fmt"
	"os"
)

type Point struct {
	x, y int
}

func main() {
	reader := bufio.NewReader(os.Stdin)
	var n, m int
	if _, err := fmt.Fscanf(reader, "%d %d\n", &n, &m); err != nil {
		return
	}

	grid := make([]string, n)
	for i := 0; i < n; i++ {
		fmt.Fscan(reader, &grid[i])
	}

	max_len := 0

	for i := 0; i < n-1; i++ {
		for j := 0; j < m-1; j++ {
			if grid[i][j] == '1' && grid[i+1][j] == '1' && grid[i][j+1] == '1' && grid[i+1][j+1] == '1' {
				if 4 > max_len {
					max_len = 4
				}
			}
		}
	}

	visited := make([][]bool, n)
	inS := make([][]bool, n)
	visitedS := make([][]bool, n)
	for i := 0; i < n; i++ {
		visited[i] = make([]bool, m)
		inS[i] = make([]bool, m)
		visitedS[i] = make([]bool, m)
	}

	dx8 := []int{-1, -1, -1, 0, 0, 1, 1, 1}
	dy8 := []int{-1, 0, 1, -1, 1, -1, 0, 1}

	dx4 := []int{-1, 1, 0, 0}
	dy4 := []int{0, 0, -1, 1}

	var S []Point
	var q []Point
	var q1 []Point

	for i := 0; i < n; i++ {
		for j := 0; j < m; j++ {
			if grid[i][j] == '0' && !visited[i][j] {
				q = q[:0]
				q = append(q, Point{i, j})
				visited[i][j] = true
				touchesBoundary := false

				for head := 0; head < len(q); head++ {
					curr := q[head]
					x, y := curr.x, curr.y

					if x == 0 || x == n-1 || y == 0 || y == m-1 {
						touchesBoundary = true
					}

					for d := 0; d < 8; d++ {
						nx, ny := x+dx8[d], y+dy8[d]
						if nx >= 0 && nx < n && ny >= 0 && ny < m {
							if grid[nx][ny] == '0' {
								if !visited[nx][ny] {
									visited[nx][ny] = true
									q = append(q, Point{nx, ny})
								}
							} else if grid[nx][ny] == '1' {
								if !inS[nx][ny] {
									inS[nx][ny] = true
									S = append(S, Point{nx, ny})
								}
							}
						}
					}
				}

				cleanup := func() {
					for _, p := range S {
						inS[p.x][p.y] = false
					}
					S = S[:0]
				}

				if touchesBoundary {
					cleanup()
					continue
				}

				if len(S) < 4 {
					cleanup()
					continue
				}

				valid := true
				for _, p := range S {
					count := 0
					for d := 0; d < 4; d++ {
						nx, ny := p.x+dx4[d], p.y+dy4[d]
						if nx >= 0 && nx < n && ny >= 0 && ny < m {
							if inS[nx][ny] {
								count++
							}
						}
					}
					if count != 2 {
						valid = false
						break
					}
				}

				if !valid {
					cleanup()
					continue
				}

				start := S[0]
				q1 = q1[:0]
				q1 = append(q1, start)
				visitedS[start.x][start.y] = true
				visitedCount := 1

				for head := 0; head < len(q1); head++ {
					curr := q1[head]
					for d := 0; d < 4; d++ {
						nx, ny := curr.x+dx4[d], curr.y+dy4[d]
						if nx >= 0 && nx < n && ny >= 0 && ny < m {
							if inS[nx][ny] && !visitedS[nx][ny] {
								visitedS[nx][ny] = true
								q1 = append(q1, Point{nx, ny})
								visitedCount++
							}
						}
					}
				}

				if visitedCount == len(S) {
					if len(S) > max_len {
						max_len = len(S)
					}
				}

				for _, p := range q1 {
					visitedS[p.x][p.y] = false
				}

				cleanup()
			}
		}
	}

	fmt.Println(max_len)
}