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

#define ll long long
#define sd(x) scanf("%d", &(x))
#define pii pair<int, int>
#define F first
#define S second
#define all(c) ((c).begin()), ((c).end())
#define sz(x) ((int)(x).size())
#define ld long double

template<class T,class U>
ostream& operator<<(ostream& os,const pair<T,U>& p){
	os<<"("<<p.first<<", "<<p.second<<")";
	return os;
}

template<class T>
ostream& operator <<(ostream& os,const vector<T>& v){
	os<<"{";
	for(int i = 0;i < (int)v.size(); i++){
		if(i)os<<", ";
		os<<v[i];
	}
	os<<"}";
	return os;
}

#ifdef LOCAL
#define cerr cout
#else
#endif

#define TRACE

#ifdef TRACE
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
	cerr << name << " : " << arg1 << std::endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
	const char* comma = strchr(names + 1, ',');cerr.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}
#else
#define trace(...)
#endif

struct sum2D{
	int n, m;
	vector<vector<int>> sm;
	sum2D(vector<vector<int>> & vec) : n(vec.size()), m(vec[0].size()){
		sm.assign(n, vector<int>(m, 0));
		vector<vector<int>> temp(n, vector<int>(m, 0));
		for(int i = 0; i < n; i++){
			for(int j = 0; j < m; j++){
				temp[i][j] = vec[i][j] + (i == 0 ? 0 : temp[i - 1][j]);
				sm[i][j] = temp[i][j] + (j == 0 ? 0 : sm[i][j - 1]);
			}
		}
	}
	int getSum(int xl, int xr, int yl, int yr){
		assert(xl >= 0 && xl < n && yl >= 0 && yl < m);
		int ret = sm[xr][yr] + (xl > 0 && yl > 0 ? sm[xl - 1][yl - 1] : 0);
		if(xl > 0) ret -= sm[xl - 1][yr];
		if(yl > 0) ret -= sm[xr][yl - 1];
		return ret;	
	}

	bool monochromatic(int xl, int xr, int yl, int yr){
		int total = (xr - xl + 1) * (yr - yl + 1);
		int white = getSum(xl, xr, yl, yr);
		return white == 0 || white == total;
	}
};
const int N = 200;
int dp[N][N][N], dp2[N][N][N], temp[N][N][N], temp2[N][N][N];
char s[N];
int main(){
	int n, m; sd(n); sd(m);
	vector<vector<int>> vec(n, vector<int>(m));
	for(int i = 0; i < n; i++){
		scanf("%s", s);
		for(int j = 0; j < m; j++) vec[i][j] = s[j] == '.';
	}
	sum2D s2d(vec);
	for(int i = 0; i < n; i++){
		for(int i2 = i; i2 < n; i2++){
			for(int j = 0; j < m; j++){
                int lo = j - 1, hi = m - 1;
				while(lo < hi){
					int mid = (lo + hi + 1) >> 1;
					if(s2d.monochromatic(i, i2, j, mid)) lo = mid;
					else hi = mid - 1;
				}
				dp[i][i2][j] = lo;
            }
		}


		for(int j = 0; j < m; j++){
			for(int j2 = j; j2 < m; j2++){
				int lo = i - 1, hi = n - 1;
				while(lo < hi){
					int mid = (lo + hi + 1) >> 1;
					if(s2d.monochromatic(i, mid, j, j2)) lo = mid;
					else hi = mid - 1;
				}
				dp2[j][j2][i] = lo;
			}
		}

	}

	for(int c = 0; c < 20; c++){
		if(dp[0][n - 1][0] >= m - 1){
			printf("%d\n", c);
			return 0;
		}
		memcpy(temp, dp, sizeof temp);
		for(int i = 0; i < n; i++) for(int i2 = i; i2 < n; i2++) for(int j = 0; j < m; j++){
			int v = temp[i][i2][j];
			if(v != m - 1)
				dp[i][i2][j] = temp[i][i2][v + 1];
		}
		memcpy(temp, dp2, sizeof temp);

		for(int j = 0; j < m; j++)for(int i = 0; i < n; i++){
			for(int j2 = j; j2 < m; j2++) {
				int v = temp[j][j2][i];
				if(v != n - 1){
					dp2[j][j2][i] = temp[j][j2][v + 1];
				}
			}
		}
		
		memcpy(temp2, dp2, sizeof temp);
		memcpy(temp, dp, sizeof temp2);

		for(int i = 0; i < n; i++) for(int j = 0; j < m; j++){
			int curr = m - 1;
			for(int i2 = i; i2 < n; i2++){
				while(curr >= j && temp2[j][curr][i] < i2) curr--;
				dp[i][i2][j] = max(curr, dp[i][i2][j]);
			}
		}

		for(int j = 0; j < m; j++)for(int i = 0; i < n; i++){
			int curr = n - 1;
			for(int j2 = j; j2 < m; j2++) {
				while(curr >= i && temp[i][curr][j] < j2) curr--;
				dp2[j][j2][i] = max(dp2[j][j2][i], curr);
			}
		}
	}
	printf("NOOOO\n");
}

Measured memory_bytes: 95064