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

#define TRACE(x) x
#define WATCH(x) TRACE(cout << #x" = " << x << endl)
#define WATCHR(a, b) TRACE(for (auto it=a; it!=b;) cout << *(it++) << " "; cout << endl)
#define WATCHC(V) TRACE({cout << #V" = "; WATCHR(V.begin(), V.end());})

#define all(x) (x).begin(), (x).end()

using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vb = vector<bool>;
using vs = vector<string>;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int MAXV = 186;
int dn[MAXV][MAXV][MAXV];
int rt[MAXV][MAXV][MAXV];

void debug(int H, int W) {
    for (int r = 0; r < 2; r++) {
        cout << "r=" << r << ": ";
        for (int c0 = 0; c0 < W; c0++) {
            for (int c1 = c0; c1 < W; c1++) {
                cout << dn[r][c0][c1] << " ";
            }
            cout << endl;
        }
        cout << endl;
    }
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);

    int H, W;
    cin >> H >> W;

    vector<string> grid(H);
    for (int h = 0; h < H; h++) {
        cin >> grid[h];
    }

    for (int r = H - 1; r >= 0; r--) {
        for (int c0 = 0; c0 < W; c0++) {
            for (int c1 = c0; c1 < W; c1++) {
                if (grid[r][c1] != grid[r][c0]) break;
                dn[r][c0][c1] = 1;
                if (r+1 < H && grid[r][c0] == grid[r+1][c0])
                    dn[r][c0][c1] += dn[r+1][c0][c1];
            }
        }
    }

    for (int c = W - 1; c >= 0; c--) {
        for (int r0 = 0; r0 < H; r0++) {
            for (int r1 = r0; r1 < H; r1++) {
                if (grid[r0][c] != grid[r1][c]) break;
                rt[c][r0][r1] = 1;
                if (c+1 < W && grid[r0][c] == grid[r0][c+1])
                    rt[c][r0][r1] += rt[c+1][r0][r1];
            }
        }
    }

    int cmx = 0;
    while (dn[0][0][W-1] != H) {
        cmx++;

        for (int r = 0; r < H; r++)
            for (int c0 = 0; c0 < W; c0++)
                for (int c1 = c0; c1 < W; c1++)
                    dn[r][c0][c1] += dn[r + dn[r][c0][c1]][c0][c1];

        for (int c = 0; c < W; c++)
            for (int r0 = 0; r0 < H; r0++)
                for (int r1 = r0; r1 < H; r1++)
                    rt[c][r0][r1] += rt[c + rt[c][r0][r1]][r0][r1];

        for (int r = 0; r < H; r++)
            for (int c0 = 0; c0 < W; c0++)
                for (int c1 = c0; c1 < W; c1++) {
                    int &t = rt[c0][r][r + dn[r][c0][c1] - 1];
                    t = max(t, c1 - c0 + 1);
                }

        for (int c = 0; c < W; c++)
            for (int r0 = 0; r0 < H; r0++)
                for (int r1 = r0; r1 < H; r1++) {
                    int &t = dn[r0][c][c + rt[c][r0][r1] - 1];
                    t = max(t, r1 - r0 + 1);
                }

        for (int r = 0; r < H; r++) {
            for (int cl = W-1; cl >= 1; cl--) {
                for (int c0 = 0; c0 < W; c0++) {
                    const int c1 = c0 + cl - 1;
                    if (c0) dn[r][c0][c1] = max(dn[r][c0][c1], dn[r][c0-1][c1]);
                    if (c1+1<W) dn[r][c0][c1] = max(dn[r][c0][c1], dn[r][c0][c1+1]);
                }
            }
        }

        for (int c = 0; c < W; c++)
            for (int rl = H-1; rl >= 1; rl--) {
                for (int r0 = 0; r0 < H; r0++) {
                    const int r1 = r0 + rl - 1;
                    if (r0) rt[c][r0][r1] = max(rt[c][r0][r1], rt[c][r0-1][r1]);
                    if (r1+1<H) rt[c][r0][r1] = max(rt[c][r0][r1], rt[c][r0][r1+1]);
                }
            }
    }

    cout << cmx << endl;

    return 0;
}



Measured memory_bytes: 50432