#ifndef HOME
#pragma GCC optimize "-O3"
#endif

#include <bits/stdc++.h>

using ll = long long;
using ull = unsigned long long;
using ld = long double;
using namespace std;

const int MX = 187;
const int INF = 1e9 + 7;

int fx[2][MX][MX][MX];
int fy[2][MX][MX][MX];

string s[MX];

int gd[MX][MX], gr[MX][MX];

bool okx(int xl, int h, int yl, int yr) {
    if (h == 0) {
        return true;
    }
    {
        int g1 = fx[0][xl][yl][yr];
        int g2 = fx[0][xl + g1][yl][yr];
        if (g1 + g2 >= h) {
            return true;
        }
    }
    {
        int r1 = fy[0][xl][xl + h - 1][yl];
        int r2 = fy[0][xl][xl + h - 1][yl + r1];
        return r1 + r2 >= yr - yl + 1;
    }
}

bool oky(int yl, int h, int xl, int xr) {
    if (h == 0) {
        return true;
    }
    {
        int g1 = fy[0][xl][xr][yl];
        int g2 = fy[0][xl][xr][yl + g1];
        if (g1 + g2 >= h) {
            return true;
        }
    }
    {
        int r1 = fx[0][xl][yl][yl + h - 1];
        int r2 = fx[0][xl + r1][yl][yl + h - 1];
        return r1 + r2 >= xr - xl + 1;
    }
}

int main() {
    ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    int n, m;
    cin >> n >> m;
    for (int i = 0; i < n; i++) {
        cin >> s[i];
    }

    for (int i = 0; i < m; i++) {
        gd[n - 1][i] = n;
    }
    for (int i = n - 2; i >= 0; i--) {
        for (int j = 0; j < m; j++) {
            if (s[i + 1][j] != s[i][j]) {
                gd[i][j] = i + 1;
            } else {
                gd[i][j] = gd[i + 1][j];
            }
        }
    }

    for (int i = 0; i < n; i++) {
        gr[i][m - 1] = m;
    }
    for (int i = n - 1; i >= 0; i--) {
        for (int j = m - 2; j >= 0; j--) {
            if (s[i][j + 1] != s[i][j]) {
                gr[i][j] = j + 1;
            } else {
                gr[i][j] = gr[i][j + 1];
            }
        }
    }

    for (int x = 0; x < n; x++) {
        for (int yl = 0; yl < m; yl++) {
            int dw = INF;
            for (int yr = yl; yr < m; yr++) {
                dw = min(dw, gd[x][yr] - x);
                if (s[x][yr] != s[x][yl]) {
                    dw = 0;
                }
                fx[0][x][yl][yr] = dw;
            }
        }
    }

    for (int y = 0; y < m; y++) {
        for (int xl = 0; xl < n; xl++) {
            int rg = INF;
            for (int xr = xl; xr < n; xr++) {
                rg = min(rg, gr[xr][y] - y);
                if (s[xr][y] != s[xl][y]) {
                    rg = 0;
                }
                fy[0][xl][xr][y] = rg;
            }
        }
    }

    for (int ANS = 0;; ANS++) {
        if (fx[0][0][0][m - 1] == n || fy[0][0][n - 1][0] == m) {
            cout << ANS << "\n";
            return 0;
        }
        for (int x = 0; x < n; x++) {
            for (int yl = 0; yl < m; yl++) {
                int cans = n - x;
                for (int yr = yl; yr < m; yr++) {
                    while (!okx(x, cans, yl, yr)) {
                        cans--;
                    }
                    fx[1][x][yl][yr] = cans;
                }
            }
        }
        for (int y = 0; y < m; y++) {
            for (int xl = 0; xl < n; xl++) {
                int cans = m - y;
                for (int xr = xl; xr < n; xr++) {
                    while (!oky(y, cans, xl, xr)) {
                        cans--;
                    }
                    fy[1][xl][xr][y] = cans;
                }
            }
        }

        memcpy(fx[0], fx[1], sizeof(fx[0]));
        memcpy(fy[0], fy[1], sizeof(fy[0]));
    }

    return 0;
}



Measured memory_bytes: 102784