import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; public class prog { private static int[] tx = { -1, 1, 0, 0 }; private static int[] ty = { 0, 0, -1, 1 }; public static void main(String[] args) throws java.lang.Exception { long start = System.currentTimeMillis(); BufferedReader bi = new BufferedReader(new InputStreamReader(System.in)); // BufferedReader bi = new BufferedReader(new FileReader("input2.txt")); Integer type = Integer.parseInt(bi.readLine()); String[] dims = bi.readLine().split(" "); Integer m = Integer.parseInt(dims[0]); Integer n = Integer.parseInt(dims[1]); String line; WeightedQuickUnionUF uf = new WeightedQuickUnionUF(n * m); char[][] matrix = new char[m][n]; int i = 0; while ((line = bi.readLine()) != null){ for (int j = 0; j < n; j++) { matrix[i][j] = line.charAt(j); } i++; } List margins = new ArrayList(); // System.out.println("Reading: " + (System.currentTimeMillis() - start)); for (i = 0; i < m; i++) { for (int j = 0; j < n; j++) { int similarNeighbors = 0; int coord = get1DCoord(i, j, n); for (int k = 0; k < 4; k++) { int x = i + tx[k]; int y = j + ty[k]; if (x >= 0 && x < m && y >= 0 && y < n) { if (matrix[i][j] == matrix[x][y]) { if (!uf.connected(coord, x * n + y)) { uf.union(coord, x * n + y); } similarNeighbors++; } } else { similarNeighbors++; } } if (similarNeighbors < 4) { margins.add(get1DCoord(i, j, n)); } } } // System.out.println("Finished uf: "+(System.currentTimeMillis() - start)); int maxSize = uf.getMaxSize(); if (type == 1) { System.out.print(maxSize); } else { if (maxSize == n * m) { System.out.println(1 + " " + 1); System.out.print(matrix[0][0]); } else { int x = 0; int y = 0; int xLastResort = -1; int yLastResort = 0; char ch = 'a'; char chLastResort = 'a'; for (int k = 0; k < margins.size(); k++) { Integer margin = margins.get(k); int[] coord2D = get2DCoord(margin, n); List validNeighbors = new LinkedList(); int[] sizes = new int[26]; for (int l = 0; l < 4; l++) { int x1 = coord2D[0] + tx[l]; int y1 = coord2D[1] + ty[l]; if (x1 >= 0 && x1 < m && y1 >= 0 && y1 < n && matrix[x1][y1] != matrix[coord2D[0]][coord2D[1]]) { validNeighbors.add(get1DCoord(x1, y1, n)); } } for (int l = 0; l < validNeighbors.size(); l++) { Integer nCoord1D = validNeighbors.get(l); int[] nCoord2D = get2DCoord(nCoord1D, n); char c = matrix[nCoord2D[0]][nCoord2D[1]]; if (l == 0) { sizes[c-'a'] += uf.getSize(nCoord1D); if(sizes[c-'a']+1 > maxSize){ maxSize = sizes[c-'a']+1; ch = c; x = coord2D[0]; y = coord2D[1]; } } for (int j = 0; j < l; j++) { if (!uf.connected(validNeighbors.get(l), validNeighbors.get(j))) { sizes[c-'a'] += uf.getSize(nCoord1D); if(sizes[c-'a']+1 > maxSize){ maxSize = sizes[c-'a']+1; ch = c; x = coord2D[0]; y = coord2D[1]; } } } } } if (maxSize != uf.getMaxSize()) { System.out.println((x + 1) + " " + (y + 1)); System.out.println(ch); } else { System.out.println((xLastResort + 1) + " " + (yLastResort + 1)); System.out.println(chLastResort); } } } // System.out.println("Ms: " + (System.currentTimeMillis() - start)); bi.close(); } private static int[] get2DCoord(int coord, int n) { return new int[] { coord / n, coord % n }; } private static int get1DCoord(int i, int j, int n) { return i * n + j; } public static class WeightedQuickUnionUF { private int[] parent; private int[] size; private int count; private int maxSize; public WeightedQuickUnionUF(int N) { count = N; parent = new int[N]; size = new int[N]; maxSize = 1; for (int i = 0; i < N; i++) { parent[i] = i; size[i] = 1; } } public int find(int p) { while (p != parent[p]) { p = parent[p]; } return p; } public int count() { return count; } public boolean connected(int p, int q) { return find(p) == find(q); } public int getMaxSize() { return maxSize; } public int getSize(int p) { return size[find(p)]; } public void union(int p, int q) { int rootP = find(p); int rootQ = find(q); if (rootP != rootQ) { if (size[rootP] < size[rootQ]) { parent[rootP] = rootQ; size[rootQ] += size[rootP]; maxSize = Math.max(maxSize, size[rootQ]); } else { parent[rootQ] = rootP; size[rootP] += size[rootQ]; maxSize = Math.max(maxSize, size[rootP]); } count--; } } } }