#include <bits/stdc++.h>
using namespace std;

void setmax(uint8_t& a, int b) {
	if (b > a) {
		a = b;
	}
}

const int MAXX = 190;
const int MAXY = 190;
const int MAXN = 20;
int X, Y;
char A[MAXX][MAXY];
uint8_t dp[MAXX][MAXX][MAXY], ndp[MAXX][MAXX][MAXY];

int main() {
	ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cin >> X >> Y;
	for (int x = 0; x < X; x++) {
		cin >> A[x];
	}

	for (int xlo = X-1; xlo >= 0; xlo--) {
		for (int xhi = xlo; xhi < X; xhi++) {
			for (int ylo = Y-1; ylo >= 0; ylo--) {
				if (xlo == xhi || (A[xhi][ylo] == A[xhi-1][ylo] && dp[xlo][xhi-1][ylo] > ylo)) {
					if (ylo < Y-1 && A[xhi][ylo] == A[xhi][ylo+1]) {
						dp[xlo][xhi][ylo] = dp[xlo][xhi][ylo+1];
					} else {
						dp[xlo][xhi][ylo] = ylo+1;
					}
				} else {
					dp[xlo][xhi][ylo] = ylo;
				}
			}
		}
	}

	int ans = 0;
	while (dp[0][X-1][0] < Y) {
		for (int xlo = 0; xlo < X; xlo++) {
			for (int xhi = xlo; xhi < X; xhi++) {
				for (int ylo = 0; ylo < Y; ylo++) {
					// append right
					if (dp[xlo][xhi][ylo] == Y) {
						ndp[xlo][xhi][ylo] = Y;
					} else {
						ndp[xlo][xhi][ylo] = dp[xlo][xhi][dp[xlo][xhi][ylo]];
					}

					// append down
					// find last position such that dp(mid) <= dp(mid+1)
					int mi = xlo-1, ma = xhi-1;
					while (ma - mi > 1) {
						int md = (mi + ma) / 2;
						setmax(ndp[xlo][xhi][ylo], min(dp[xlo][md][ylo], dp[md+1][xhi][ylo]));
						if (dp[xlo][md][ylo] <= dp[md+1][xhi][ylo]) {
							ma = md;
						} else {
							mi = md;
						}
					}
					for (int i = ma; i <= ma+1 && i <= xhi-1; i++) {
						setmax(ndp[xlo][xhi][ylo], min(dp[xlo][i][ylo], dp[i+1][xhi][ylo]));
					}
				}
			}
		}
		memcpy(dp, ndp, sizeof(dp));
		ans++;
	}
	cout << ans << endl;

	return 0;
}
