#include <bits/stdc++.h>
// iostream is too mainstream
#include <cstdio>
// bitch please
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <list>
#include <cmath>
#include <iomanip>
#include <time.h>
#define dibs reserve
#define OVER9000 1234567890
#define ALL_THE(CAKE,LIE) for(auto LIE =CAKE.begin(); LIE != CAKE.end(); LIE++)
#define tisic 47
#define soclose 1e-8
#define chocolate win
// so much chocolate
#define patkan 9
#define ff first
#define ss second
#define abs(x) (((x) < 0)?-(x):(x))
#define uint unsigned int
#define dbl long double
#define pi 3.14159265358979323846
using namespace std;
// mylittledoge

using cat = long long;

#ifdef DONLINE_JUDGE
	// palindromic tree is better than splay tree!
	#define lld I64d
#endif

int main() {
	cin.sync_with_stdio(0);
	cin.tie(0);
	cout << fixed << setprecision(10);
	int H, W;
	cin >> H >> W;
	vector<string> A(H);
	for(int i = 0; i < H; i++) cin >> A[i];
	constexpr int MX = 16;
	vector< vector< vector<uint8_t> > > max_h[MX+1];
	vector< vector< vector<uint8_t> > > max_w[MX+1];
	for(int v = 0; v <= MX; v++) {
		max_h[v].resize(W+1, vector< vector<uint8_t> >(W+1));
		max_w[v].resize(H+1, vector< vector<uint8_t> >(H+1));
		for(int i = 0; i < H; i++) for(int j = i+1; j <= H; j++) {
			max_w[v][i][j].resize(W+1, 0);
			for(int k = 0; k <= W; k++) max_w[v][i][j][k] = k;
		}
		for(int i = 0; i < W; i++) for(int j = i+1; j <= W; j++) {
			max_h[v][i][j].resize(H+1, 0);
			for(int k = 0; k <= H; k++) max_h[v][i][j][k] = k;
		}
	}

	for(int i = 0; i < H; i++) for(int j = W-1; j >= 0; j--) {
		if(j < W-1 && A[i][j] != A[i][j+1]) max_w[0][i][i+1][j] = j+1;
		else max_w[0][i][i+1][j] = max_w[0][i][i+1][j+1];
	}
	for(int i = 0; i < W; i++) for(int j = H-1; j >= 0; j--) {
		if(j < H-1 && A[j][i] != A[j+1][i]) max_h[0][i][i+1][j] = j+1;
		else max_h[0][i][i+1][j] = max_h[0][i][i+1][j+1];
	}
	for(int d = 2; d <= H; d++) for(int i = 0; i <= H-d; i++)
		for(int j = 0; j < W; j++) if(A[i][j] == A[i+1][j])
			max_w[0][i][i+d][j] = min(max_w[0][i+1][i+d][j], max_w[0][i][i+1][j]);
	for(int d = 2; d <= W; d++) for(int i = 0; i <= W-d; i++)
		for(int j = 0; j < H; j++) if(A[j][i] == A[j][i+1])
			max_h[0][i][i+d][j] = min(max_h[0][i+1][i+d][j], max_h[0][i][i+1][j]);

	for(int v = 1; v <= MX; v++) {
		for(int i = 0; i < H; i++) for(int j = 0; j < W; j++) for(int k = j+1; k <= W; k++) {
			int h1 = max_h[v-1][j][k][i];
			if(h1 == i) break;
			int h2 = max_h[v-1][j][k][h1];
			max_w[v][i][h2][j] = max(max_w[v][i][h2][j], (uint8_t)k);
		}
		for(int i = 0; i < H; i++) {
			for(int k = H-1; k > i; k--) for(int j = 0; j < W; j++)
				max_w[v][i][k][j] = max(max_w[v][i][k][j], max_w[v][i][k+1][j]);
			for(int j = i+1; j <= H; j++) for(int l = 0; l < W; l++) {
				int w2 = max_w[v-1][i][j][l];
				max_w[v][i][j][l] = max(max_w[v][i][j][l], max_w[v-1][i][j][w2]);
			}
		}
		for(int i = 0; i < W; i++) for(int j = 0; j < H; j++) for(int k = j+1; k <= H; k++) {
			int w1 = max_w[v-1][j][k][i];
			if(w1 == i) break;
			int w2 = max_w[v-1][j][k][w1];
			max_h[v][i][w2][j] = max(max_h[v][i][w2][j], (uint8_t)k);
		}
		for(int i = 0; i < W; i++) {
			for(int k = W-1; k > i; k--) for(int j = 0; j < H; j++)
				max_h[v][i][k][j] = max(max_h[v][i][k][j], max_h[v][i][k+1][j]);
			for(int j = i+1; j <= W; j++) for(int l = 0; l < H; l++) {
				int h2 = max_h[v-1][i][j][l];
				max_h[v][i][j][l] = max(max_h[v][i][j][l], max_h[v-1][i][j][h2]);
			}
		}
	}

	for(int i = 0; i <= MX; i++) if(max_w[i][0][H][0] == W) {
		cout << i << "\n";
		return 0;
	}
	return 0;
}

// look at my code
// my code is amazing


Measured memory_bytes: 148992