#include <bits/stdc++.h>

using namespace std;
using int64 = long long;

constexpr int DEBUG = 0;

template<typename T>
vector<vector<T>> Make2DVector(int d1, int d2, T default_value) {
  return vector<vector<T>>(d1, vector<T>(d2, default_value));
}

// Vector
template<typename T> ostream& operator<<(ostream& s, const vector<T>& v) {
  int len = v.size();
  s << "[";
	for (int i = 0; i < len; i++) {
    if (i > 0) s << ", ";
		s << v[i];
  }
  s << "]";
  return s;
}

template<class T> inline bool UpdateMin(T& a, T b) {
  if (a > b) { a = b; return 1; } return 0;
}

template<class T> inline bool UpdateMax(T& a, T b) {
  if (a < b) { a = b; return 1; } return 0;
}

int SolveMaxRectangle(const vector<int>& input_xs, int w) {
  vector<int> xs(input_xs.begin(), input_xs.end());
  xs.push_back(0);

  int max = w;
  stack<pair<int, int>> stack;
  for (int i = 0; i < xs.size(); i++) {
    if (stack.empty()) {
      stack.push(make_pair(xs[i], i));
    } else {
      if (xs[i] >= stack.top().first) {
        stack.push(make_pair(xs[i], i));
      } else {
        int push_index = i;
        while (!stack.empty() && xs[i] < stack.top().first) {
          int r_width = i - stack.top().second + 1;
          int r_area = r_width * stack.top().first;
          UpdateMax(max, r_area);
          push_index = stack.top().second;
          // if (DEBUG) {
          //   cout << "i: " << i << endl;
          //   cout << "stack.top().second: " << stack.top().second << endl;
          //   cout << "v: " << stack.top().first << endl;
          //   cout << "r_area: " << r_area << endl;
          // }
          stack.pop();
        }

        stack.push(make_pair(xs[i], push_index));
      }
    }
  }
  return max;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);

  int h, w;
  cin >> h >> w;
  vector<string> board(h);
  for (int r = 0; r < h; r++) {
    cin >> board[r];
  }

  vector<vector<int>> dp1 = Make2DVector(h - 1, w, -1);
  for (int r = 0; r < h - 1; r++) {
    int current = -1;
    for (int c = w - 1; c >= 0; c--) {
      if (c == w - 1) {
        current = board[r][c] == board[r + 1][c];
        dp1[r][c] = 1;
      } else {
        if ((board[r][c] == board[r + 1][c]) == current) {
          dp1[r][c] = dp1[r][c + 1] + 1;
        } else {
          current = board[r][c] == board[r + 1][c];
          dp1[r][c] = 1;
        }
      }
    }
  }

  if (DEBUG) {
    for (int r = 0; r < h - 1; r++) {
      cout << "dp1[" << r << "]: " << dp1[r] << endl;
    }
  }

  int ans = 0;
  for (int c = 0; c < w; c++) {
    vector<int> xs(h - 1);
    for (int r = 0; r < h - 1; r++) {
      xs[r] = dp1[r][c];
    }
    if (DEBUG) {
      cout << "SolveMaxRectangle(" << c << ")" << endl;
      cout << "xs: " << xs << endl;
    }
    int max_rectanle = SolveMaxRectangle(xs, w - c);
    if (DEBUG) cout << "c: " << c << " max_rectangle: " << max_rectanle << endl;
    UpdateMax(ans, max_rectanle);
  }
  cout << ans << endl;
}


/*
Writer: SPD_9X2
https://atcoder.jp/contests/arc081/tasks/arc081_d

長方形にできる必要十分条件は、
内側にある四つ角の周り全てに関して、周りにある黒が偶数個
→そのような条件を満たす四つ角グリッドを考えると最大長方形になる

幅1の長方形に関しては全て作れるので、ans初期値はmax(H,W)
*/

#include <bits/stdc++.h>
using namespace std;
#define rep(i,n,m) for(int (i)=(n);(i)<(m);(i)++)
#define rrep(i,n,m) for(int (i)=(n);(i)>(m);(i)--)
using ll = long long;
const ll mod = 1000000007;
const ll half = 500000004;

int LRIH(vector<int>& lis){

    vector<vector<int>> stk(0);

    int ans = 0;
    int N = lis.size();

    rep(i,0,N){

        if (stk.size() == 0){
            stk.push_back({lis[i],i});
        }else if (stk[stk.size()-1][0] < lis[i]){
            stk.push_back({lis[i],i});
        }else if (stk[stk.size()-1][0] > lis[i]){

            int lastpos = -1;

            while ( (stk.size()>0) && (stk[stk.size()-1][0] > lis[i])){

                int nh = stk[stk.size()-1][0];
                int np = stk[stk.size()-1][1];
                lastpos = np;
                stk.pop_back();

                ans = max(ans , (nh+1)*(i-np+1));
            }

            stk.push_back({lis[i] , lastpos});
        }
    }

    return ans;
}

int main(){

    int H,W;
    cin >> H >> W;

    vector<vector<char>> S(H,vector<char> (W));
    rep(i,0,H){
        rep(j,0,W){
            cin >> S[i][j];
        }
    }

    vector<vector<int>> lis(H-1,vector<int> (W-1,0));

    rep(i,0,H-1){
        rep(j,0,W-1){
            if (S[i][j] == '#') lis[i][j] += 1;
            if (S[i+1][j] == '#') lis[i][j] += 1;
            if (S[i][j+1] == '#') lis[i][j] += 1;
            if (S[i+1][j+1] == '#') lis[i][j] += 1;
            lis[i][j] %= 2;
        }
    }

    vector<vector<int>> hist(H-1,vector<int> (W,0));

    rep(i,0,H-1){
        rep(j,0,W-1){

            if (lis[i][j] == 0){
                if (i==0){
                    hist[i][j] = 1;
                }else{
                    hist[i][j] = hist[i-1][j] + 1;
                }
            }

        }
    }

    int ans = max(H,W);
    rep(i,0,H-1){
        ans = max(ans , LRIH(hist[i]));
    }

    cout << ans << endl;
}