#include <bits/stdc++.h>

#define F first
#define S second
#define prev azaza
#define MP make_pair
#define PB push_back

using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned char uchar;

const uchar max_n = 188, max_ans = 17, inf = 220;

uchar dph[max_n][max_n][max_n][max_ans];
uchar dpv[max_n][max_n][max_n][max_ans];
int cr[max_n][max_n];
int cd[max_n][max_n];

int n, m;
char f[max_n][max_n];


int solve() {
    for (int i = 0; i < n; ++i) {
        cr[i][m - 1] = 1;
        for (int j = m - 2; j >= 0; --j) {
            if (f[i][j] == f[i][j + 1]) {
                cr[i][j] = cr[i][j + 1] + 1;
            } else {
                cr[i][j] = 1;
            }
        }
    }
    for (int j = 0; j < m; ++j) {
        cd[n - 1][j] = 1;
        for (int i = n - 2; i >= 0; --i) {
            if (f[i][j] == f[i + 1][j]) {
                cd[i][j] = cd[i + 1][j] + 1;
            } else {
                cd[i][j] = 1;
            }
        }
    }
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            int max_w = inf;
            for (int h = 1; i + h <= n; ++h) {
                if (f[i + h - 1][j] != f[i][j]) {
                    max_w = 0;
                } else {
                    max_w = min(max_w, cr[i + h - 1][j]);
                }
                dpv[i][j][h][0] = max_w;
            }
        }
    }

    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            int max_h = inf;
            for (int w = 1; j + w <= m; ++w) {
                if (f[i][j + w - 1] != f[i][j]) {
                    max_h = 0;
                } else {
                    max_h = min(max_h, cd[i][j + w - 1]);
                }
                dph[i][j][w][0] = max_h;
            }
        }
    }
    for (int ans = 1; ans < max_ans; ++ans) {
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < m; ++j) {
                int max_w = m - j;
                int max_h = n - i;
                vector<pair<int, int>> hw;
                for (int w = 1; w <= max_w; ++w) {
                    int top_h = dph[i][j][w][ans - 1];
                    int h = top_h == max_h ? top_h : top_h + dph[i + top_h][j][w][ans - 1];
                    hw.emplace_back(h, w);
                }
                for (int h = 1; i + h <= n; ++h) {
                    int left_w = dpv[i][j][h][ans - 1];
                    if (left_w == max_w) {
                        dpv[i][j][h][ans] = left_w;
                    } else {
                        dpv[i][j][h][ans] = left_w + dpv[i][j + left_w][h][ans - 1];
                    }
                    while (!hw.empty() && hw.back().F < h) {
                        hw.pop_back();
                    }
                    if (!hw.empty()) {
                        dpv[i][j][h][ans] = max(dpv[i][j][h][ans], (uchar)hw.back().S);
                    }
                }

                ///// COPYPASTE !!!!!!!!!!!!

                vector<pair<int, int>> wh;
                for (int h = 1; h <= max_h; ++h) {
                    int left_w = dpv[i][j][h][ans - 1];
                    int w = left_w == max_w ? left_w : left_w + dpv[i][j + left_w][h][ans - 1];
                    wh.emplace_back(w, h);
                }

                for (int w = 1; j + w <= m; ++w) {
                    int top_h = dph[i][j][w][ans - 1];
                    if (top_h == max_h) {
                        dph[i][j][w][ans] = top_h;
                    } else {
                        dph[i][j][w][ans] = top_h + dph[i + top_h][j][w][ans - 1];
                    }
                    while (!wh.empty() && wh.back().F < w) {
                        wh.pop_back();
                    }
                    if (!wh.empty()) {
                        dph[i][j][w][ans] = max(dph[i][j][w][ans], (uchar)wh.back().S);
                    }
                }
            }
        }
    }
    for (int ans = 0; ans < max_ans; ++ans) {
        if (dpv[0][0][n][ans] == m) {
            return ans;
            //cout << ans << endl;
            break;
        }
    }
    /*for (int ans = 0; ans < max_ans; ++ans) {
        if (dph[0][0][m][ans] == n) {
            cout << ans << endl;
            break;
        }
    }*/
}

int main()
{
    //freopen("input.txt", "r", stdin);
    cin >> n >> m;
    for (int i = 0; i < n; ++i) {
        scanf("%s", f[i]);
    }
    cout << solve() << endl;
    return 0;
}

// think 25 min
// write 45 min


Measured memory_bytes: 219520