#include <bits/stdc++.h>

using std::cin;
using std::cout;
using std::cerr;

using std::vector;
using std::string;
using std::pair;
using std::make_pair;

using std::min;
using std::max;
using std::abs;

template <typename T>
T input() {
    T res;
    cin >> res;
    return res;
}

int main() {
#ifndef LOCAL
#define TASK "video"
    freopen(TASK ".in", "r", stdin);
    freopen(TASK ".out", "w", stdout);
#endif
    std::iostream::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    uint32_t n, m;
    cin >> n >> m;
    while (cin.peek() == '\n')
        cin.get();

    vector<string> field(n);
    for (uint32_t i = 0; i != n; ++i)
        std::getline(cin, field[i]);

    vector<vector<uint32_t>> dp(2 * n, vector<uint32_t>(2 * m, 0));
    for (uint32_t i = 0; i != 2 * n; ++i)
        for (uint32_t j = 0; j != 2 * m; ++j) {
            if (i != 0)
                dp[i][j] += dp[i - 1][j];
            if (j != 0)
                dp[i][j] += dp[i][j - 1];

            if (i != 0 and j != 0)
                dp[i][j] -= dp[i - 1][j - 1];
            if (i != 0 and j != 0) {
                int good = 0;
                good += (field[i % n][j % m] == field[(i - 1) % n][(j - 1) % m]);
                good += (field[i % n][j % m] == field[(i - 1) % n][j % m]);
                good += (field[i % n][j % m] == field[i % n][(j - 1) % m]);
                good += (field[i % n][j % m] == field[i % n][j % m]);
                dp[i][j] += (good == 4);
            }
        }

    uint32_t ans = 0;
    for (uint32_t i = n - 1; i != 2 * n; ++i)
        for (uint32_t j = m - 1; j != 2 * m; ++j) {
            uint32_t cur_ans = 0;
            cur_ans += dp[i][j];
            cur_ans -= dp[i + 1 - n][j];
            cur_ans -= dp[i][j + 1 - m];
            cur_ans += dp[i + 1 - n][j + 1 - m];

            ans = max(ans, cur_ans);
        }
    cout << ans << std::endl;
    return 0;
}