#include <fstream>
#include <vector>
#include <string>
#include <algorithm>
#include <cassert>

using namespace std;

int solve(
	int x0, int x1,
	int y0, int y1,
	vector<string>& F) {
	int cnt = 0;
	x0 = max(0, x0); y0 = max(0, y0);
	for (int i = x0; i <= x1-1; ++i) {
		for (int j = y0; j <= y1 - 1; ++j) {
			char a = F[i][j], b = F[i + 1][j],
				c = F[i][j + 1], d = F[i + 1][j + 1];
			if (a == b && b == c && c == d) {
				cnt++;
			}
		}
	}
	return cnt;
}

int n, m;

vector<vector<int>> even_v, diff_v;

int solve_vstrip(int x0, int x1, int y0, int y1, vector<string>& field) {
	assert(y1 - y0 == 1);
	return (even_v[x1 + 1][y0] - even_v[x0][y0]) -
		(diff_v[x1 + 1][y0] - diff_v[x0][y0]) - 1;
}

void shift_left(
	int& x0, int& y0, int x1, int y1,
	int& next_answer,
	vector<string>& field) {
	assert(y0 > 0);
	int delta = solve_vstrip(x0, x1, y0 - 1, y0, field);
	delta -= solve_vstrip(x0, x1, y1 - 1, y1, field);
	next_answer += delta;
	y0--;
}
void shift_right(
	int& x0, int& y0, int x1, int y1,
	int& next_answer,
	vector<string>& field) {
	assert(y0 < m);
	int delta = -solve(x0, x1, y0, y0 + 1, field);
	delta += solve(x0, x1, y1, y1 + 1, field);
	next_answer += delta;
	y0++;
}

void shift_up(
	int& x0, int& y0, int x1, int y1,
	int& next_answer,
	vector<string>& field) {
	assert(x0 > 0);
	int delta = solve(x0 - 1, x0, y0, y1, field);
	delta -= solve(x1 - 1, x1, y0, y1, field);
	next_answer += delta;
	x0--;
}
void shift_down(
	int& x0, int& y0, int x1, int y1,
	int& next_answer,
	vector<string>& field) {
	assert(x0 < n);
	int delta = -solve(x0, x0 + 1, y0, y1, field);
	delta += solve(x1, x1 + 1, y0, y1, field);
	next_answer += delta;
	x0++;
}

void init_memo(vector<string>& field) {
	for (int& i : even_v[0]) i = 0;
	for (int& i : diff_v[0]) i = 0;
	for (int i = 0; i < field.size(); ++i) {
		for (int j = 0; j < field[i].size()-1; ++j) {
			if (field[i][j] == field[i][j + 1])
				even_v[i + 1][j]++;
			else
				diff_v[i + 1][j]++;
		}
	}
}

int main() {
	ifstream fin("video.in");
	ofstream fout("video.out");
	fin >> n >> m;
	vector<string> field(2 * n);
	for (int i = 0; i < n; ++i) {
		fin >> field[i];
		field[i] += field[i];
		field[n + i] = field[i];
	}
	even_v.assign(field.size() + 1, vector<int>(field[0].size(), 0));
	diff_v.assign(field.size() + 1, vector<int>(field[0].size(), 0));
	init_memo(field);
	int max_answer = 0, x0 = 0, y0 = 0;
	max_answer = solve(0, n-1, 0, m-1, field);
	int next_answer = max_answer;
	for (int stage = 1; stage <= min(n, m); ++stage) {
		for (int i = 0; i < m - stage; ++i) {
			if (stage & 1)
				shift_right(x0, y0, x0 + n - 1, y0 + m - 1, next_answer, field);
			else
				shift_left(x0, y0, x0 + n - 1, y0 + m - 1, next_answer, field);
			max_answer = max(max_answer, next_answer);
		}
		for (int i = 0; i < n - stage; ++i) {
			if (stage & 1)
				shift_down(x0, y0, x0 + n - 1, y0 + m - 1, next_answer, field);
			else
				shift_up(x0, y0, x0 + n - 1, y0 + m - 1, next_answer, field);

			max_answer = max(max_answer, next_answer);
		}
	}
	fout << max_answer << "\n";
	return 0;
}