#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<utility>
#include<cassert>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
const ll mod = 1000000007;
const ll INF = mod * mod;
typedef pair<int, int> P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
typedef pair<ll, ll> LP;
typedef vector<ll> vec;
typedef vector<string> svec;
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-8;

char mp[185][185];
int mosw[185][185][185];
int mosh[185][185][185];
int copw[185][185][185];
int coph[185][185][185];

int num[185][185];
bool is_zero(int lx, int ly, int rx, int ry) {
	int cnt = num[rx][ry];
	if (lx > 0)cnt -= num[lx - 1][ry];
	if (ly > 0)cnt -= num[rx][ly - 1];
	if (lx > 0 && ly > 0)cnt += num[lx - 1][ly - 1];
	if (cnt == 0 || cnt == (rx - lx + 1)*(ry - ly + 1))return true;
	else return false;
}
int h, w;
void debug() {
	cout << "-------------------" << endl;
	rep(i, h) {
		rep(j, w) {
			cout << i << " " << j << endl;
			Rep(k, i, h) {
				cout << mosw[i][j][k] << endl;
			}
			Rep(k, j, w) {
				cout << mosh[i][j][k] << endl;
			}
		}
	}

}
void solve() {
	cin >> h >> w;
	rep(i, h) {
		rep(j, w) {
			cin >> mp[i][j];
			if (mp[i][j] == '#')num[i][j] = 1;
			if (i > 0)num[i][j] += num[i - 1][j];
			if (j > 0)num[i][j] += num[i][j - 1];
			if (i > 0 && j > 0)num[i][j] -= num[i - 1][j - 1];
		}
	}
	int tmp = 0;
	rep(i, h) {
		Rep(j, i, h) {
			int cur = 0;
			while (cur < w) {
				if (!is_zero(i, cur, j, cur)) {
					mosw[i][cur][j] = cur - 1;
					cur++;
				}
				else {
					int memo = cur;
					while (cur + 1 < w&&is_zero(i, memo, j, cur + 1)) {
						cur++;
					}
					Rep(k, memo, cur + 1) {
						mosw[i][k][j] = cur;
					}
					cur++;
				}
			}
		}
	}
	rep(i, w) {
		Rep(j, i, w) {
			int cur = 0;
			while (cur < h) {
				if (!is_zero(cur, i, cur, j)) {
					mosh[cur][i][j] = cur - 1;
					cur++;
				}
				else {
					int memo = cur;
					while (cur + 1 < h&&is_zero(memo, i, cur + 1, j)) {
						cur++;
					}
					Rep(k, memo, cur + 1) {
						mosh[k][i][j] = cur;
					}
					cur++;
				}
			}
		}
	}
	//debug();
	while (mosw[0][0][h - 1] < w - 1) {
		tmp++;
		rep(i, h) {
			rep(j, w) {
				Rep(k, i, h) {
					if (mosw[i][j][k] + 1 < w) {
						copw[i][j][k] = mosw[i][mosw[i][j][k] + 1][k];
					}
					else {
						copw[i][j][k] = w - 1;
					}
				}
				Rep(k, j, w) {
					if (mosh[i][j][k] + 1 < h) {
						coph[i][j][k] = mosh[mosh[i][j][k]+1][j][k];
					}
					else {
						coph[i][j][k] = h - 1;
					}
				}
			}
		}
		rep(i, h) {
			rep(j, w) {
				Rep(k, i, h) {
					mosw[i][j][k] = max(mosw[i][j][k], copw[i][j][k]);
				}
				Rep(k, j, w) {
					mosh[i][j][k] = max(mosh[i][j][k], coph[i][j][k]);
				}
				int id = w - 1;
				Rep(k, i, h) {
					while (id>=j&&mosh[i][j][id] < k)id--;
					mosw[i][j][k] = max(mosw[i][j][k], id);
				}
				id = h - 1;
				Rep(k, j, w) {
					while (id >= i && mosw[i][j][id] < k)id--;
					mosh[i][j][k] = max(mosh[i][j][k], id);
				}
			}
		}
		//debug();
		//break;
	}
	cout << tmp << endl;
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << fixed << setprecision(10);
	//cout << pow(1/6000.0, 1.0 / 25) << endl;
	//init();
	solve();
	//cout << "finish" << endl;
	//stop
	return 0;
}


Measured memory_bytes: 99328