#include <bits/stdc++.h>

typedef long long ll;

using namespace std;

const int N = 190;

int n, m;
string s[N];
int dp[2][2][N][N][N];

void update(int curl, int x1, int y1, int x2, int y2)
{
    curl &= 1;
    curl ^= 1;
    if (x1 <= x2 && y1 <= y2)
    {
        dp[curl][0][x1][y1][y2] = max(dp[curl][0][x1][y1][y2], x2 - x1 + 1);
        dp[curl][1][x1][x2][y1] = max(dp[curl][1][x1][x2][y1], y2 - y1 + 1);
    }
}

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

    for (int i = n - 1; i >= 0; i--)
    {
        for (int L = 0; L < m; L++)
        {
            for (int R = L; R < m; R++)
            {
                if (R > L && s[i][L] != s[i][R]) break;
                dp[0][0][i][L][R] = (i + 1 < n && s[i + 1][L] == s[i][L] ? dp[0][0][i + 1][L][R] : 0) + 1;
            }
        }
    }
    for (int j = m - 1; j >= 0; j--)
    {
        for (int L = 0; L < n; L++)
        {
            for (int R = L; R < n; R++)
            {
                if (R > L && s[L][j] != s[R][j]) break;
                dp[0][1][L][R][j] = (j + 1 < m && s[L][j] == s[L][j + 1] ? dp[0][1][L][R][j + 1] : 0) + 1;
            }
        }
    }
    for (int it = 0; ; it++)
    {
        for (int i = 0; i < N; i++)
        {
            for (int j = 0; j < N; j++)
            {
                for (int k = 0; k < N; k++)
                {
                    dp[it & 1][0][i][j][k] = max(dp[0][0][i][j][k], dp[1][0][i][j][k]);
                    dp[it & 1][1][i][j][k] = max(dp[0][1][i][j][k], dp[1][1][i][j][k]);
                }
            }
        }
        vector<vector<vector<int> > > down(N, vector<vector<int> >(N, vector<int>(N)));
        vector<vector<vector<int> > > right(N, vector<vector<int> >(N, vector<int>(N)));
        for (int L = 0; L < n; L++)
        {
            for (int R = L; R < n; R++)
            {
                for (int j = 0; j < m; j++)
                {
                    int x = dp[it & 1][1][L][R][j];
                    int L1 = j, R1 = j + x - 1;
                    if (R1 >= 0)
                    down[L][L1][R1] = max(down[L][L1][R1], R - L + 1);
                }
            }
        }
        for (int i = 0; i < N; i++)
        {
            for (int j = 0; j < N; j++)
            {
                for (int k = N - 2; k >= 0; k--)
                {
                    down[i][j][k] = max(down[i][j][k], down[i][j][k + 1]);
                }
            }
        }
        for (int i = 0; i < n; i++)
        {
            for (int L = 0; L < m; L++)
            {
                for (int R = L; R < m; R++)
                {
                    dp[it & 1][0][i][L][R] = max(dp[it & 1][0][i][L][R], down[i][L][R]);
                }
            }
        }
        for (int i = 0; i < n; i++)
        {
            for (int L = 0; L < m; L++)
            {
                for (int R = L; R < m; R++)
                {
                    int x = dp[it & 1][0][i][L][R];
                    int L1 = i, R1 = i + x - 1;
                    if (R1 >= 0)
                    right[L1][R1][L] = max(right[L1][R1][L], R - L + 1);
                }
            }
        }
        for (int i = 0; i < N; i++)
        {
            for (int j = N - 2; j >= 0; j--)
            {
                for (int k = 0; k < N; k++)
                {
                    right[i][j][k] = max(right[i][j][k], right[i][j + 1][k]);
                }
            }
        }
        for (int L = 0; L < n; L++)
        {
            for (int R = L; R < n; R++)
            {
                for (int j = 0; j < m; j++)
                {
                    dp[it & 1][1][L][R][j] = max(dp[it & 1][1][L][R][j], right[L][R][j]);
                }
            }
        }
        if (dp[it & 1][0][0][0][m - 1] == n) cout << it, exit(0);
        if (dp[it & 1][1][0][n - 1][0] == m) cout << it, exit(0);
        for (int i = 0; i < n; i++)
        {
            for (int L = 0; L < m; L++)
            {
                for (int R = m - 1; R >= 0; R--)
                {
                    if (R < m - 1) dp[(it & 1) ^ 1][0][i][L][R] = max(dp[(it & 1) ^ 1][0][i][L][R],
                                                                      dp[(it & 1) ^ 1][0][i][L][R + 1]);
                    int i2 = i + dp[it & 1][0][i][L][R];
                    int i3 = i2 + dp[it & 1][0][i2][L][R];
                    update(it, i, L, i3 - 1, R);
                }
            }
        }
        for (int j = 0; j < m; j++)
        {
            for (int L = 0; L < n; L++)
            {
                for (int R = n - 1; R >= L; R--)
                {
                    if (R < n - 1) dp[(it & 1) ^ 1][1][L][R][j] = max(dp[(it & 1) ^ 1][1][L][R][j],
                                                                      dp[(it & 1) ^ 1][1][L][R + 1][j]);
                    int j2 = j + dp[it & 1][1][L][R][j];
                    int j3 = j2 + dp[it & 1][1][L][R][j2];
                    update(it, L, j, R, j3 - 1);
                }
            }
        }
    }
}


Measured memory_bytes: 163544