#include <iostream>
#include <iomanip>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cassert>
#include <string>
#include <set>
#include <map>
#include <random>
#include <bitset>
#include <string>
#include <unordered_set>
#include <unordered_map>
#include <deque>
#include <queue>
#define rep(i, n) for (int i = 0; i < (n); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()

using namespace std;
using ll = long long;
using ld = long double;

const int N = 190, M = 19;
char s[N];
int a[N][N];
short dp[2][M][N][N][N];

void rel(short &c1, short c2) {
	c1 = max(c1, c2);
}

int main() {
#ifdef LOCAL
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
	ios_base::sync_with_stdio(0); cin.tie(0);
	int n, m;
	cin >> n >> m;
	rep(i, n) {
		cin >> s;
		rep(j, m)
			a[i][j] = (s[j] == '#' ? 1 : 0);
	}
	for (int lx = n - 1; lx >= 0; lx--)
		for (int dy = 1; dy <= m; dy++)
			for (int ly = 0, ry = dy; ry <= m; ly++, ry++) {
				if (dy > 2)
					dp[0][0][lx][ly][ry] = min(dp[0][0][lx][ly][ry - 1], dp[0][0][lx][ly + 1][ry]);
				else if (a[lx][ly] == a[lx][ry - 1]) {
					if (lx < n - 1 && a[lx][ly] == a[lx + 1][ly] && a[lx][ry - 1] == a[lx + 1][ry - 1])
						dp[0][0][lx][ly][ry] = dp[0][0][lx + 1][ly][ry];
					else
						dp[0][0][lx][ly][ry] = lx + 1;
				}
				else
					dp[0][0][lx][ly][ry] = lx;
			}
	for (int ly = m - 1; ly >= 0; ly--)
		for (int dx = 1; dx <= n; dx++)
			for (int lx = 0, rx = dx; rx <= n; lx++, rx++) {
				if (dx > 2)
					dp[1][0][ly][lx][rx] = min(dp[1][0][ly][lx][rx - 1], dp[1][0][ly][lx + 1][rx]);
				else if (a[lx][ly] == a[rx - 1][ly]) {
					if (ly < m - 1 && a[lx][ly] == a[lx][ly + 1] && a[rx - 1][ly] == a[rx - 1][ly + 1])
						dp[1][0][ly][lx][rx] = dp[1][0][ly + 1][lx][rx];
					else
						dp[1][0][ly][lx][rx] = ly + 1;
				}
				else
					dp[1][0][ly][lx][rx] = ly;
			}
	int c = 0;
	while (dp[0][c][0][0][m] < n) {
		for (int lx = n - 1; lx >= 0; lx--)
			for (int dy = 1; dy <= m; dy++)
				for (int ly = 0, ry = dy; ry <= m; ly++, ry++) {
					if (dp[0][c][lx][ly][ry] == n)
						dp[0][c + 1][lx][ly][ry] = n;
					else {
						// cout << (int) dp[0][c][lx][ly][ry] << endl;
						dp[0][c + 1][lx][ly][ry] = dp[0][c][dp[0][c][lx][ly][ry]][ly][ry];
					}
				}
		for (int ly = m - 1; ly >= 0; ly--)
			for (int dx = 1; dx <= n; dx++)
				for (int lx = 0, rx = dx; rx <= n; lx++, rx++) {
					if (dp[1][c][ly][lx][rx] == m)
						dp[1][c + 1][ly][lx][rx] = m;
					else
						dp[1][c + 1][ly][lx][rx] = dp[1][c][dp[1][c][ly][lx][rx]][lx][rx];
					rel(dp[0][c + 1][lx][ly][dp[1][c + 1][ly][lx][rx]], rx);
				}
		rep(lx, n)
			for (int dy = m; dy > 0; dy--)
				for (int ly = 0, ry = dy; ry <= m; ly++, ry++) {
					rel(dp[1][c + 1][ly][lx][dp[0][c + 1][lx][ly][ry]], ry);
					if (ry < m)
						rel(dp[0][c + 1][lx][ly][ry], dp[0][c + 1][lx][ly][ry + 1]);
					if (ly > 0)
						rel(dp[0][c + 1][lx][ly][ry], dp[0][c + 1][lx][ly - 1][ry]);
					if (lx > 0)
						rel(dp[0][c + 1][lx][ly][ry], dp[0][c + 1][lx - 1][ly][ry]);
				}
		rep(ly, m)
			for (int dx = n; dx > 0; dx--)
				for (int lx = 0, rx = dx; rx <= n; lx++, rx++) {
					if (rx < n)
						rel(dp[1][c + 1][ly][lx][rx], dp[1][c + 1][ly][lx][rx + 1]);
					if (rx > 0)
						rel(dp[1][c + 1][ly][lx][rx], dp[1][c + 1][ly][lx - 1][rx]);
					if (ly > 0)
						rel(dp[1][c + 1][ly][lx][rx], dp[1][c + 1][ly - 1][lx][rx]);
				}
		c++;
	}
	cout << c;
}


Measured memory_bytes: 459136