//ll f(vvi arr){
//    int n = sz(arr);
//    int m = sz(arr[0]);
//    for(auto &_ : arr)
//        _.insert(_.begin(),-1);
//    arr.insert(arr.begin(),vi(m+1,-1));
//    vvi up(n+2,vi(m+2,0));
//    rep(i,1,n)
//        rep(j,1,m){
//            up[i][j] = up[i-1][j]+1;
//            if(arr[i][j] != 0)
//                up[i][j] = 0;
//        }
//    ll ans = 0;
//    rep(i,1,n){
//        vpii stacc(1,{0,0}); //thicc
//        rep(j,1,m+1){
//            int last_popped = j;
//            while(stacc.back().Y > up[i][j]){
//                ll w = j-stacc.back().X;
//                ll h = stacc.back().Y;
//                ans = max(ans,(w+1)*(h+1));
//                last_popped = stacc.back().X;
//                stacc.pop_back();
//            }
//            stacc.pb({last_popped,up[i][j]});
//        }
//
//    }
//    return ans;
//}
//void _(){
//    int n,m;
//    cin >> n >> m;
//    vs grid(n);
//    cin >> grid;
//    vvi tmp(n);
//    rep(i,0,n-1)
//        rep(j,1,m-1)
//            tmp[i].pb(grid[i][j] != grid[i][j-1]);
//    vvi ans(n-1);
//    rep(i,1,n-1)
//        rep(j,0,m-2)
//            ans[i-1].pb(tmp[i][j] != tmp[i-1][j]);
//    ll ret = f(ans);
//    ret = max(ret,ll(max(n,m)));
//    print(ret);
//}
//
#include <iomanip>
#include <algorithm>
#include <cassert>
#include <vector>
#include <utility>
#include <iostream>
#include <string>
#define pb push_back
#define REP_INT(i,l,r) for(int i = l; i <= r; ++i)
#define GET_REP_MACRO(_1,_2,_3,_4,NAME,...) NAME
#define rep(...) GET_REP_MACRO(__VA_ARGS__,REP_ANY,REP_INT)(__VA_ARGS__)
#define all(v) (v).begin(), (v).end()
#define sz(v) ll(v.size())
#define X first
#define Y second
#define T1 template<typename T> static
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef vector<string> vs;
typedef vector<vi> vvi;
typedef pair<int, int> pii;
typedef vector<pii> vpii;
T1 ostream& operator<<(ostream& stream, const vector<T>& t);
T1 istream& read(T, T, istream& = cin);
T1 istream& operator>>(istream& stream, vector<T>& t){
    return read(all(t), stream);
}
T1 istream& read(T b, T e, istream& stream){
    for(T it = b; it != e; ++it)
        stream >> *it;
    return stream;
}
T1 void print(T x, string end = "\n"){
    cout << x << end;
}
ll f(vvi arr){
    int n = sz(arr);
    int m = sz(arr[0]);
    for(auto &_ : arr)
        _.insert(_.begin(),-1);
    arr.insert(arr.begin(),vi(m+1,-1));
    vvi up(n+2,vi(m+2,0));
    rep(i,1,n)
        rep(j,1,m){
            up[i][j] = up[i-1][j]+1;
            if(arr[i][j] != 0)
                up[i][j] = 0;
        }
    ll ans = 0;
    rep(i,1,n){
        vpii stacc(1,{0,0}); //thicc
        rep(j,1,m+1){
            int last_popped = j;
            while(stacc.back().Y > up[i][j]){
                ll w = j-stacc.back().X;
                ll h = stacc.back().Y;
                ans = max(ans,(w+1)*(h+1));
                last_popped = stacc.back().X;
                stacc.pop_back();
            }
            stacc.pb({last_popped,up[i][j]});
        }
    }
    return ans;
}
void _(){
    int n,m;
    cin >> n >> m;
    vs grid(n);
    cin >> grid;
    vvi tmp(n);
    rep(i,0,n-1)
        rep(j,1,m-1)
            tmp[i].pb(grid[i][j] != grid[i][j-1]);
    vvi ans(n-1);
    rep(i,1,n-1)
        rep(j,0,m-2)
            ans[i-1].pb(tmp[i][j] != tmp[i-1][j]);
    ll ret = f(ans);
    ret = max(ret,ll(max(n,m)));
    print(ret);
}
int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(15);
        _();
}


Measured memory_bytes: 80000