#include<iomanip>
#include<limits>
#include<thread>
#include<utility>
#include<iostream>
#include<string>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<numeric>
#include<cassert>
#include<random>
#include<chrono>
#include<unordered_set>
#include<unordered_map>
#include<fstream>
#include<list>
#include<functional>
#include<bitset>
#include<complex>
#include<tuple>
using namespace std;
typedef unsigned long long int ull;
typedef long long int ll;
typedef pair<ll,ll> pll;
typedef long double D;
#define F first
#define S second
const ll E=1e18+7;
const ll MOD=1000000007;



int main(){
    int h,w;
    cin>>h>>w;
    vector<string> A(h);
    for(auto &I:A){cin>>I;}
    vector<vector<vector<ll>>> dp1(h+1,vector<vector<ll>>(w+1,vector<ll>(h+1,0)));
    vector<vector<vector<ll>>> dp2(h+1,vector<vector<ll>>(w+1,vector<ll>(w+1,0)));
    vector<vector<vector<ll>>> next1(h+1,vector<vector<ll>>(w+1,vector<ll>(h+1,0)));
    vector<vector<vector<ll>>> next2(h+1,vector<vector<ll>>(w+1,vector<ll>(w+1,0)));
    
    for(int i=0;i<=h;i++){
        for(int t=0;t<=w;t++){
            for(int j=0;j<=h;j++){
                dp1[i][t][j]=t;
            }
            for(int j=0;j<=w;j++){
                dp2[i][t][j]=i;
            }
        }
    }
    
    
    for(int i=0;i<h;i++){
        for(int t=0;t<w;t++){
            int j=t;
            while(j<w && A[i][j]==A[i][t]){j++;}
            dp1[i][t][i]=j;
            j=i;
            while(j<h && A[j][t]==A[i][t]){j++;}
            dp2[i][t][t]=j;
        }
    }
    for(int i=0;i<h;i++){
        for(int t=0;t<w;t++){
            for(int j=i+1;j<h;j++){
                if(A[j][t]==A[i][t]){dp1[i][t][j]=min(dp1[i][t][j-1],dp1[j][t][j]);}
                else{break;}
            }
            for(int j=t+1;j<w;j++){
                if(A[i][t]==A[i][j]){dp2[i][t][j]=min(dp2[i][t][j-1],dp2[i][j][j]);}
                else{break;}
            }
        }
    }
    
    for(int i=0;;i++){
        
        if(dp1[0][0][h-1]==w || dp2[0][0][w-1]==h){cout<<i<<endl; return 0;}
        for(int x=0;x<h;x++){
            for(int y=0;y<w;y++){
                for(int j=x;j<h;j++){
                    if(dp1[x][y][j]==y){continue;}
                    dp1[x][y][j]=max(dp1[x][y][j],dp1[x][dp1[x][y][j]][j]);
                }
                for(int j=y;j<w;j++){
                    if(dp2[x][y][j]==x){continue;}
                    dp2[x][y][j]=max(dp2[x][y][j],dp2[dp2[x][y][j]][y][j]);
                }
            }
        }
        next1=dp1;
        next2=dp2;
        for(int x=0;x<h;x++){
            for(int y=0;y<w;y++){
                ll last=y;
                for(int j=h-1;j>=x;j--){
                    if(last>=dp1[x][y][j]){continue;}
                    for(ll t=last;t<dp1[x][y][j];t++){next2[x][y][t]=max(next2[x][y][t],j+1LL);}
                    last=dp1[x][y][j];
                }
                last=x;
                for(int j=w-1;j>=y;j--){
                    if(last>=dp2[x][y][j]){continue;}
                    for(ll t=last;t<dp2[x][y][j];t++){next1[x][y][t]=max(next1[x][y][t],j+1LL);}
                    last=dp2[x][y][j];
                }
            }
        }
        dp1=next1;
        dp2=next2;
        /*
        for(int x=0;x<h;x++){
            for(int y=0;y<w;y++){
                for(int j=x;j<h;j++){
                    cout<<1<<" "<<i+1<<" "<<x<<" "<<y<<" "<<j<<" "<<dp1[x][y][j]<<endl;
                }
            }
        }
        for(int x=0;x<h;x++){
            for(int y=0;y<w;y++){
                for(int j=y;j<w;j++){
                    cout<<2<<" "<<i+1<<" "<<x<<" "<<y<<" "<<j<<" "<<dp2[x][y][j]<<endl;
                }
            }
        }
        */
        
    }
    
    
    
    return 0;
}


Measured memory_bytes: 209152