#define y1 askjdkasldjlkasd
#include <bits/stdc++.h>
#undef y1

using namespace std;

#define pb push_back
#define mp make_pair
#define fi(a, b) for(int i=a; i<=b; i++)
#define fj(a, b) for(int j=a; j<=b; j++)
#define fo(a, b) for(int o=a; o<=b; o++)
#define fdi(a, b) for(int i=a; i>=b; i--)
#define fdj(a, b) for(int j=a; j>=b; j--)
#define fdo(a, b) for(int o=a; o>=b; o--)
#define sz(x) (int)x.size()

typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef pair<int, int> pii;
typedef vector<pii> vpii;
typedef pair<ll, ll> pll;
typedef vector<pll> vpll;
typedef vector<ll> vll;

#ifdef LOCAL
#define err(...) fprintf(stderr, __VA_ARGS__)
#else
#define err(...) while (0)
#endif

double START_TIME;

void exit() {
#ifdef LOCAL	
	cerr << "TIME: " << setprecision(5) << fixed << (clock() - START_TIME) / CLOCKS_PER_SEC << endl;
#endif	
	exit(0);
}

template<typename A, typename B>
ostream& operator<<(ostream& os, pair<A, B> p) {
	os << "(" << p.first << ", " << p.second << ")";
	return os;
}

template<typename T>
ostream& operator<<(ostream& os, vector<T> v) {
	fi(0, sz(v) - 1) {
		os << v[i] << " ";
	}
	return os;
}

template<typename T>
ostream& operator<<(ostream& os, set<T> t) {
	for (auto z : t) {
		os << z << " ";
	}
	return os;
}

template<typename T1, typename T2>
ostream& operator<<(ostream& os, map<T1, T2> t) {
	cerr << endl;
	for (auto z : t) {
		os << "\t" << z.first << " -> " << z.second << endl;
	}
	return os;
}

#ifdef LOCAL
#define dbg(x) {cerr << __LINE__ << "\t" << #x << ": " << x << endl;}
#define dbg0(x, n) {cerr << __LINE__ << "\t" << #x << ": "; for (int ABC = 0; ABC < n; ABC++) cerr << x[ABC] << ' '; cerr << endl;}
#else
#define dbg(x) while(0){}
#define dbg0(x, n) while(0){}
#endif

#ifdef LOCAL
#define ass(x) if (!(x)) { cerr << __LINE__ << "\tassertion failed: " << #x << endl, abort(); }
#else
#define ass(x) assert(x)
#endif

///////////////////////////////////////////////////

const int MAX = 194;
const int LOG = 41;

int h, w;
int a[MAX][MAX];
int d[2][MAX][MAX][MAX];
int ptr[MAX][MAX][MAX];

int calc() {
	fo(1, LOG - 1) {
		memcpy(d[1], d[0], sizeof(d[1]));
		for (int x = 0; x < h; x++) {
			for (int y0 = 0; y0 < w; y0++) {
				ptr[x][y0][y0] = y0;
				for (int y1 = y0; y1 < w; y1++) {
					{//ver
						int xx = d[1][x][y0][y1];
						if (xx == 0) {
							d[0][x][y0][y1] = xx;
						} else if (xx <= x) {
							d[0][x][y0][y1] = d[1][xx - 1][y0][y1];
						} else {
							d[0][x][y0][y1] = xx;
						}
					}
					if (y1 > y0) {//hor
						int p = ptr[x][y0][y1 - 1];
						while (p + 1 < y1) {							
							int v1 = d[1][x][y0][p];
							int v2 = d[1][x][p + 1][y1];
							int cur = max(v1, v2);
							int v3 = d[1][x][y0][p + 1];
							int v4 = d[1][x][p + 2][y1];
							int nxt = max(v3, v4);
							if (nxt > cur) break;							
							p++;
						}
						ptr[x][y0][y1] = p;
						int v1 = d[1][x][y0][p];
						int v2 = d[1][x][p + 1][y1];
						int cur = max(v1, v2);
						d[0][x][y0][y1] = min(d[0][x][y0][y1], cur);
					}
				}
			}
		}
		if (d[0][h - 1][0][w - 1] == 0) {
			return o;
		}
	}	
	assert(false);
	return 41;
}

void solve () {
	fi(0, h - 1) fj(0, w - 1) {		
		fdo(i, 0) {
			if (a[i][j] != a[o][j]) break;
			d[0][i][j][j] = o;
		}
	}
	for (int x = 0; x < h; x++) {
		for (int y0 = 0; y0 < w; y0++) {
			int cur = d[0][x][y0][y0];
			for (int y1 = y0 + 1; y1 < w; y1++) {
				if (a[x][y0] != a[x][y1]) cur = x + 1;
				cur = max(cur, d[0][x][y1][y1]);
				d[0][x][y0][y1] = cur;
			}
		}
	}
	int ans = 41;
	if (d[0][h - 1][0][w - 1] == 0) {
		ans = 0;
	} else {
		ans = calc();
	}
	assert(ans < 41);
	printf("%d\n", ans);
}

int main() {
#ifdef LOCAL
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
	START_TIME = (double)clock();
#endif
	
	scanf("%d %d", &h, &w);
	fi(0, h - 1) {
		char str[241];
		scanf("%s", str);
		fj(0, w - 1) a[i][j] = (str[j] == '#' ? 1 : 0);
	}
	solve();

	exit();
	return 0;
}





Measured memory_bytes: 86016