// Dmitry _kun_ Sayutin (2019)

#include <bits/stdc++.h>

using std::cin;
using std::cout;
using std::cerr;

using std::vector;
using std::map;
using std::array;
using std::set;
using std::string;

using std::pair;
using std::make_pair;

using std::tuple;
using std::make_tuple;
using std::get;

using std::min;
using std::abs;
using std::max;
using std::swap;

using std::unique;
using std::sort;
using std::generate;
using std::reverse;
using std::min_element;
using std::max_element;

#ifdef LOCAL
#define LASSERT(X) assert(X)
#else
#define LASSERT(X) {}
#endif

template <typename T>
T input() {
    T res;
    cin >> res;
    LASSERT(cin);
    return res;
}

template <typename IT>
void input_seq(IT b, IT e) {
    std::generate(b, e, input<typename std::remove_reference<decltype(*b)>::type>);
}

#define SZ(vec)         int((vec).size())
#define ALL(data)       data.begin(),data.end()
#define RALL(data)      data.rbegin(),data.rend()
#define TYPEMAX(type)   std::numeric_limits<type>::max()
#define TYPEMIN(type)   std::numeric_limits<type>::min()

const int max_n = 185;

int n, m;
char field[max_n + 3][max_n + 3];

int sums[max_n + 3][max_n + 3];

int get_sum(int i, int j, int l, int r) {
    int res = sums[r][j];

    if (i)
        res -= sums[r][i - 1];
    if (l)
        res -= sums[l - 1][j];

    if (i and l)
        res += sums[l - 1][i - 1];

    return res;
}

bool is_monochrome(int i, int j, int l, int r) {
    int sm = get_sum(i, j, l, r);

    int area = (j - i + 1) * (r - l + 1);

    return (sm == 0 or sm == area);
}

const int max_kek = 17;

int16_t dp[max_n][max_n][max_n][1 + max_kek];

int main() {
    std::iostream::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    // code here
    cin >> n >> m;
    for (int i = 0; i != n; ++i)
        for (int j = 0; j != m; ++j)
            cin >> field[i][j];

    for (int i = 0; i != n; ++i)
        for (int j = 0; j != m; ++j) {
            sums[i][j] = 0;
            if (field[i][j] == '#')
                ++sums[i][j];

            if (i)
                sums[i][j] += sums[i - 1][j];
            if (j)
                sums[i][j] += sums[i][j - 1];
            if (i and j)
                sums[i][j] -= sums[i - 1][j - 1];
        }

    fprintf(stderr, "%0.2f kek\n", clock() / double(CLOCKS_PER_SEC));
    
    // k = 0
    for (int i = 0; i != m; ++i)
        for (int j = i; j != m; ++j) {
            int r = -1;
            for (int l = 0; l != n; ++l) {
                if (r == -1)
                    r = l - 1;
                
                while (r != n - 1 and is_monochrome(i, j, l, r + 1))
                    ++r;

                if (r == l - 1)
                    r = -1;

                dp[i][j][l][0] = r;
            }
        }

    fprintf(stderr, "%0.2f kek2\n", clock() / double(CLOCKS_PER_SEC));
    
    for (int k = 1; k <= max_kek; ++k) {
        for (int l = 0; l != n; ++l) {
            for (int i = 0; i != m; ++i) {
                int ppp = i;
                
                for (int j = i; j != m; ++j) {
                    dp[i][j][l][k] = -1;

                    if (dp[i][j][l][k - 1] != -1) {
                        int rr = dp[i][j][l][k - 1];

                        if (rr != n - 1 and dp[i][j][rr + 1][k - 1] != -1)
                            rr = dp[i][j][rr + 1][k - 1];

                        dp[i][j][l][k] = rr;
                    }

                    auto eval = [&](int t) {
                        if (dp[i][t][l][k - 1] < dp[t + 1][j][l][k - 1])
                            return make_pair(dp[i][t][l][k - 1], 0);
                        else
                            return make_pair(dp[t + 1][j][l][k - 1], 1);
                    };

                    int16_t& ans = dp[i][j][l][k];
                    if (i <= j - 1) {
                        auto e1 = eval(i);
                        auto e2 = eval(j - 1);
                        ans = max(ans, e1.first);
                        ans = max(ans, e2.first);

                        if (e1.second != e2.second) {
                            int lo = i;
                            int hi = j - 1;

                            while (hi - lo > 1) {
                                int mi = lo + (hi - lo) / 2;

                                auto ee = eval(mi);
                                if (ee.second == e1.second)
                                    lo = mi;
                                else
                                    hi = mi;
                            }

                            ans = max(ans, eval(lo).first);
                            ans = max(ans, eval(hi).first);
                        }
                    }

                    // if (i <= j - 1) {
                    //     while (ppp + 1 <= j - 1 and eval(ppp).second == 0)
                    //         ppp += 1;

                    //     ans = max(ans, eval(ppp).first);
                    //     if (ppp + 1 <= j - 1)
                    //         ans = max(ans, eval(ppp+1).first);
                    // }
                }
            }
        }
    }

    fprintf(stderr, "%0.2f kek3\n", clock() / double(CLOCKS_PER_SEC));
    
    int ans = 0;
    while (dp[0][m - 1][0][ans] != n - 1)
        ++ans;

    cout << ans << "\n";
    
    return 0;
}


Measured memory_bytes: 221696