// Original C++ solution (slower):
// ===================================

//   author: M_sea

//   website: http://m-sea-blog.com/

// ===================================

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;



int read() {

    int X=0,w=1; char c=getchar();

    while (c<'0'||c>'9') { if (c=='-') w=-1; c=getchar(); }

    while (c>='0'&&c<='9') X=X*10+c-'0',c=getchar();

    return X*w;

}



const int N=185+10;



int n,m;

char a[N][N]; int s[N][N];

int dp[2][N][N][N];



int same(int lx,int ly,int rx,int ry) {

    int o=s[rx][ry]-s[lx-1][ry]-s[rx][ly-1]+s[lx-1][ly-1];

    return o==(rx-lx+1)*(ry-ly+1)||o==0;

}



int f(int o,int i,int j,int k) {

    int L=i,R=j-1,res=0;

    while (L<=R) {

        int mid=(L+R)>>1;

        res=max(res,min(dp[o][i][mid][k],dp[o][mid+1][j][k]));

        if (dp[o][i][mid][k]<dp[o][mid+1][j][k]) R=mid-1;

        else L=mid+1;

    }

    return res;

}



int main() {

    n=read(),m=read();

    for (int i=1;i<=n;++i) scanf("%s",a[i]+1);

    for (int i=1;i<=n;++i)

        for (int j=1;j<=m;++j)

            s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+(a[i][j]=='#');

    if (same(1,1,n,m)) { puts("0"); return 0; }

    for (int i=1;i<=n;++i)

        for (int j=i;j<=n;++j)

            for (int k=1,t;k<=m;k=t) {

                t=k;

                while (t<=m&&same(i,k,j,t)) ++t;

                for (int p=k;p<t;++p) dp[0][i][j][p]=t-1;

                if (k==t) dp[0][i][j][k]=k-1,++t;

            }

    for (int w=1;;++w) {

        int o=w&1,p=o^1;

        for (int i=1;i<=n;++i)

            for (int j=i;j<=n;++j)

                for (int k=1;k<=m;++k) {

                    int t=dp[p][i][j][k];

                    if (t==m) dp[o][i][j][k]=m;

                    else dp[o][i][j][k]=max(dp[p][i][j][t+1],f(p,i,j,k));

                }

        if (dp[o][1][n][1]==m) { printf("%d\n",w); break; }

    }

    return 0;

}

// Optimized solution to the same problem (faster):
#include <cstring>

#include <cstdio>



inline int min(int a, int b) { return a < b ? a : b; }

inline int max(int a, int b) { return a > b ? a : b; }



const int _ = 200;



int n, m, s[_][_], dp[2][_][_][_]; char a[_][_];



inline int chk(int x1, int y1, int x2, int y2) {

    int res = s[x2][y2] - s[x2][y1 - 1] - s[x1 - 1][y2] + s[x1 - 1][y1 - 1];

    return res == (y2 - y1 + 1) * (x2 - x1 + 1) || res == 0;

}



inline int bs(int c, int i, int j, int k) {

    int l = i, r = j - 1, res = 0;

    while (l <= r) {

        int mid = (l + r) >> 1;

        res = max(res, min(dp[c][i][mid][k], dp[c][mid + 1][j][k]));

        if (dp[c][i][mid][k] < dp[c][mid + 1][j][k]) r = mid - 1; else l = mid + 1;

    }

    return res;

}



int main() {

    scanf("%d %d", &n, &m);

    for (int i = 1; i <= n; ++i) scanf("%s", a[i] + 1);

    for (int i = 1; i <= n; ++i)

        for (int j = 1; j <= m; ++j)

            s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + (a[i][j] == '#');

    if (chk(1, 1, n, m)) { puts("0"); return 0; }

    for (int i = 1; i <= n; ++i)

        for (int j = i; j <= n; ++j)

            for (int l, k = 1; k <= m; k = l) {

                l = k;

                while (l <= m && chk(i, k, j, l)) ++l;

                for (int x = k; x < l; ++x) dp[0][i][j][x] = l - 1;

                if (k == l) dp[0][i][j][k] = k - 1, ++l;

            }

    for (int x = 1; ; ++x) {

        int c = x & 1, c_1 = c ^ 1;

        for (int i = 1; i <= n; ++i)

            for (int j = i; j <= n; ++j)

                for (int k = 1; k <= m; ++k) {

                    int x = dp[c_1][i][j][k];

                    if (x == m) dp[c][i][j][k] = m;

                    else dp[c][i][j][k] = max(dp[c_1][i][j][x + 1], bs(c_1, i, j, k));

                }

        if (dp[c][1][n][1] == m) { printf("%d\n", x); return 0; }

    }

    return 0;

}


// Fastest known solution for this problem: