//#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
const int inf_int = 1e9 + 100;
const ll inf_ll = 1e18;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef long double dbl;
#define pb push_back
#define eb emplace_back
const double pi = 3.1415926535898;
#define dout if(debug) cout
#define fi first
#define se second
#define sp setprecision
#define sz(a) (int(a.size()))
#define mp make_pair
#define all(a) a.begin(),a.end()
bool debug = 0;
const int MAXN = 1e5 + 100;
const int LOG = 21;
const int mod = 1e9 + 7;
const int MX = (1e7 + 100) * 1.5;
typedef long long li;
const li MOD = 1000000000949747713ll;

template<class T1, class T2>
std::ostream &operator<<(std::ostream &out, const std::pair<T1, T2> &rhs) {
    out << "( " << rhs.first << " , " << rhs.second << " )";
    return out;
}


string s[200];

int pref[256][256];

int dp_r[190][190][190];
int dp_d[190][190][190];

int new_dp_r[190][190][190];
int new_dp_d[190][190][190];

void solve() {
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; ++i) {
        cin >> s[i];
        s[i] = "#" + s[i];
        dout <<s[i]<<" "<<endl;
    }

    for (int i = 1; i <= n; ++i) {
        for (int e = 1; e <= m; ++e) {
            pref[i][e] = pref[i - 1][e] + pref[i][e - 1] - pref[i - 1][e - 1];
            if (s[i][e] == '#')
                pref[i][e]++;
        }
    }

    auto get_pref = [&](int i1, int j1, int i2, int j2) {
        return pref[i2][j2] - pref[i2][j1 - 1] - pref[i1 - 1][j2] + pref[i1 - 1][j1 - 1];
    };

    auto is_equal = [&](int i1, int j1, int i2, int j2) {
        int sum = get_pref(i1, j1, i2, j2);
        int area = (i2 - i1 + 1) * (j2 - j1 + 1);
        return sum == 0 || sum == area;
    };


    for (int i1 = 1; i1 <= n; ++i1) {
        for (int j1 = 1; j1 <= m; ++j1) {
            for (int i2 = i1; i2 <= n; ++i2) {
                int l = j1, r = m;
                int ans = j1-1;
                while (l <= r) {
                    int mid = (l + r) >> 1;
                    if (is_equal(i1, j1, i2, mid)) {
                        ans = mid;
                        l = mid + 1;
                    } else {
                        r = mid - 1;
                    }
                }
                dp_r[i1][j1][i2] = ans;
            }
        }
    }
    for (int j1 = 1; j1 <= m; ++j1) {
        for (int j2 = j1; j2 <= m; ++j2) {
            for (int i1 = 1; i1 <= n; ++i1) {
                int l = i1, r = n;
                int ans = i1-1;
                while (l <= r) {
                    int mid = (l + r) >> 1;
                    if (is_equal(i1, j1, mid, j2)) {
                        ans = mid;
                        l = mid + 1;
                    } else {
                        r = mid - 1;
                    }
                }
                dp_d[i1][j1][j2] = ans;
            }
        }
    }
    dout <<"!! "<<dp_r[1][1][n]<<endl;

    for (int step = 0;; ++step) {
        if (dp_r[1][1][n] == m) {
            cout << step;
            return;;
        }

        for (int i1 = 1; i1 <= n; ++i1) {
            for (int j1 = 1; j1 <= m; ++j1) {
                for (int i2 = i1; i2 <= n; ++i2) {
                    int cur = dp_r[i1][j1][i2];
                    if (cur < m) {
                        cur = dp_r[i1][cur + 1][i2];
                    }
                    new_dp_r[i1][j1][i2] = cur;
                }
            }
        }

        for (int i1 = 1; i1 <= n; ++i1) {
            for (int j1 = 1; j1 <= m; ++j1) {
                for (int j2 = j1; j2 <= m; ++j2) {
                    int cur = dp_d[i1][j1][j2];
                    if (cur < n) {
                        cur = dp_d[cur + 1][j1][j2];
                    }
                    new_dp_d[i1][j1][j2] = cur;
                }

            }
        }

        for (int i1 = 1; i1 <= n; ++i1) {
            for (int j1 = 1; j1 <= m; ++j1) {
                for (int i2 = i1; i2 <= n; ++i2) {
                    int cur = new_dp_r[i1][j1][i2];
                    while (cur + 1 <= m && new_dp_d[i1][j1][cur + 1] >= i2) {
                        cur++;
                    }
                    dp_r[i1][j1][i2] = cur;
                }
                for (int j2 = j1; j2 <= m; ++j2) {
                    int cur = new_dp_d[i1][j1][j2];
                    while (cur + 1 <= n && new_dp_r[i1][j1][cur + 1] >= j2) {
                        cur++;
                    }
                    dp_d[i1][j1][j2] = cur;
                }
            }
        }

    }

}

signed main() {
#ifdef zxc
    debug = 0;
    freopen("../input.txt", "r", stdin);
    //  freopen("../output.txt", "w", stdout);
#else

#endif //zxc
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cout.setf(ios::fixed);
    cout.precision(20);

    int t = 1;
    while (t--)
        solve();
    if (debug)
        cerr << endl << "time : " << (1.0 * clock() / CLOCKS_PER_SEC) << endl;
}

Measured memory_bytes: 107008