#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<bool> vb;
typedef pair<int, int> pii;
#define f first
#define s second
#define pb push_back
#define FOR(i, a, b) for (int i = a; i < b; i++)
#define SORT(v) sort(v.begin(), v.end())
#define RSORT(v) sort(v.rbegin(), v.rend())
vector<vector<char>> grid;
int cols;
int rows;
int peak = 0;
vector<vb> visited;
deque<pair<int, pii>> dq;
void floodfill(int r, int c, int p) {
if(visited[r][c]) return;
visited[r][c] = true;
peak = max(p, peak);
if(r > 0) {
if(grid[r][c] != grid[r-1][c] && grid[r-1][c] != '.') dq.push_back({p+1, {r-1, c}});
else if(grid[r-1][c] != '.') dq.push_front({p, {r-1, c}});
}
if(r < rows-1) {
if(grid[r][c] != grid[r+1][c] && grid[r+1][c] != '.') dq.push_back({p+1, {r+1, c}});
else if(grid[r+1][c] != '.') dq.push_front({p, {r+1, c}});
}
if(c > 0) {
if(grid[r][c] != grid[r][c-1] && grid[r][c-1] != '.') dq.push_back({p+1, {r, c-1}});
else if(grid[r][c-1] != '.') dq.push_front({p, {r, c-1}});
}
if(c < cols-1) {
if(grid[r][c] != grid[r][c+1] && grid[r][c+1] != '.') dq.push_back({p+1, {r, c+1}});
else if(grid[r][c+1] != '.') dq.push_front({p, {r, c+1}});
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int h, w;
cin>>h>>w;
cols = w;
rows = h;
grid = vector<vector<char>> (h, vector<char>(w));
visited = vector<vector<bool>> (h, vector<bool>(w));
FOR(i, 0, h) {
FOR(j, 0, w) {
cin>>grid[i][j];
}
}
dq.push_front({0, {0, 0}});
while(!dq.empty()) {
pair<int, pii> goat = dq.front();
dq.pop_front();
floodfill(goat.s.f, goat.s.s, goat.f);
}
cout<<peak+1<<endl;;
}