#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>

using namespace std;
#define PB push_back
#define MP make_pair
#define LL long long
//#define int LL
#define FOR(i,a,b) for(int i = (a); i <= (b); i++)
#define RE(i,n) FOR(i,1,n)
#define REP(i,n) FOR(i,0,(int)(n)-1)
#define R(i,n) REP(i,n)
#define VI vector<int>
#define PII pair<int,int>
#define LD long double
#define FI first
#define SE second
#define st FI
#define nd SE
#define ALL(x) (x).begin(), (x).end()
#define SZ(x) ((int)(x).size())

#define unordered_map __fast_unordered_map
template<class Key, class Value, class Hash = std::hash<Key>>
using unordered_map = __gnu_pbds::gp_hash_table<Key, Value, Hash>;

template<class C> void mini(C &a4, C b4) { a4 = min(a4, b4); }
template<class C> void maxi(C &a4, C b4) { a4 = max(a4, b4); }

template<class TH> void _dbg(const char *sdbg, TH h){ cerr<<sdbg<<'='<<h<<endl; }
template<class TH, class... TA> void _dbg(const char *sdbg, TH h, TA... a) {
  while(*sdbg!=',')cerr<<*sdbg++;
  cerr<<'='<<h<<','; _dbg(sdbg+1, a...);
}

template<class T> ostream &operator<<(ostream& os, vector<T> V) {
  os << "["; for (auto vv : V) os << vv << ","; return os << "]";
}
template<class L, class R> ostream &operator<<(ostream &os, pair<L,R> P) {
  return os << "(" << P.st << "," << P.nd << ")";
}

#ifdef LOCAL
#define debug(...) _dbg(#__VA_ARGS__, __VA_ARGS__)
#else
#define debug(...) (__VA_ARGS__)
#define cerr if(0)cout
#endif

const int MaxDim = 200;

int H, W;
string board[MaxDim];

int max_right[MaxDim][MaxDim][MaxDim];

void Start() {
  for (int i = 0; i < H; ++i) {
    for (int j = 0; j < W; ++j) {
      int max_size = W - j;
      for (int d = 1; i + d <= H; ++d) {
        for (int k = 0; k < max_size; ++k) {
          if (board[i+d-1][j+k] != board[i][j]) {
            max_size = k;
            break;
          }
        }
        max_right[i][j][d] = max_size;
        debug(i, j, d, max_right[i][j][d]);
      }
    }
  }
}

int old_right[MaxDim][MaxDim][MaxDim];
int old_dn[MaxDim][MaxDim][MaxDim];

void Process() {
  memcpy(old_right, max_right, sizeof(max_right));

  for (int i = 0; i < H; ++i) {
    for (int j = 0; j < W; ++j) {
      int aptr = H, bptr = H;
      for (int w = 1; j + w <= W; ++w) {
        while (aptr > i && max_right[i][j][aptr - i] < w) { --aptr; }
        while (bptr > aptr && max_right[aptr][j][bptr - aptr] < w) { --bptr; }
        old_dn[i][j][w] = bptr - i;
        debug(i, j, w, old_dn[i][j][w]);
      }
    }
  }

  for (int i = 0; i < H; ++i) {
    for (int j = 0; j < W; ++j) {
      for (int h = 1; i + h <= H; ++h) {
        const int fst = old_right[i][j][h] + j;
        const int snd = old_right[i][fst][h] + fst;
        max_right[i][j][h] = snd - j;
      }

      for (int w = 1; j + w <= W; ++w) {
        const int fst = old_dn[i][j][w] + i;
        maxi(max_right[i][j][fst - i], w);
      }

      for (int h = H - i; h > 0; --h) {
        maxi(max_right[i][j][h], max_right[i][j][h + 1]);
      }

      for (int h = 1; i + h <= H; ++h) {
        debug(i, j, h, max_right[i][j][h]);
      }
    }
  }

  debug(max_right[0][0][H]);
}


int32_t main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout << fixed << setprecision(11);
  cerr << fixed << setprecision(6);

  cin >> H >> W;
  for (int i = 0; i < H; ++i) {
    cin >> board[i];
  }

  Start();
  int ans = 0;
  while (max_right[0][0][H] < W) {
    ++ans;
    Process();
    debug(ans);
  }

  cout << ans << "\n";
}



Measured memory_bytes: 92416