#include <cassert>
#include <iostream>
#include <map>
#include <string>
#include <vector>

using namespace std;

typedef long long ll;

void transpose(vector<string>& v) {
  int r = (int)v.size();
  int c = (int)v[0].size();
  if(c < r) return;
  vector<string> nv;
  nv.reserve(c);
  for(int i = 0; i < c; i++) nv.push_back("");
  for(int i = 0; i < r; i++) for(int j = 0; j < c; j++) nv[j] += v[i][j];
  v.swap(nv);
  assert(v[0].size() <= v.size());
}

const int NUM_BITS = 4;
const int LOW_ORDER = (1 << NUM_BITS) - 1;

void cleanse(vector<vector<int>>& windows) {
  for(int i = 0; i < (int)windows.size(); i++) {
    for(int j = ((int)windows.size())-1; j >= 0 && i < (int)windows.size(); j--) {
      if(i == j) continue;
      bool dominated = true;
      assert(windows[i].size() == windows[j].size());
      for(int a = 0; dominated && a < (int)windows[i].size(); a++) {
        dominated &= windows[i][a] >= windows[j][a];
      }
      if(dominated) windows.erase(windows.begin() + j);
    }
  }
}

void mergeWindow(int& x, int y, vector<int>& window, ll& state, int numCols) {
  if(x == y) return;
  assert(x != y);
  assert(x > 0 && y > 0);
  if(x > y) swap(x, y);
  assert(x < (int)window.size());
  assert(y < (int)window.size());
  if(x == 2 && y == 3) {
    x = 1;
    window[1] = window[2] + window[3];
    window[2] = 0;
    window[3] = 0;
    ll nstate = 0;
    for(int i = 0; i < numCols; i++) {
      int curr = (state >> (i * NUM_BITS)) & LOW_ORDER;
      if(curr == 2 || curr == 3) nstate |= (1LL << (i * NUM_BITS));
      else nstate |= (((ll)curr) << (i * NUM_BITS));
    }
    state = nstate;
  }
  else {
    window[x] += window[y];
    window[y] = 0;
    ll nstate = 0;
    for(int i = 0; i < numCols; i++) {
      int curr = (state >> (i * NUM_BITS)) & LOW_ORDER;
      if(curr == y) nstate |= (((ll)x) << (i * NUM_BITS));
      else nstate |= (((ll)curr) << (i * NUM_BITS));
    }
    state = nstate;
  }
}

void normalize(ll& key, vector<int>& assignment, int numSquares) {
  assert((int)assignment.size() >= 4);
  map<int, int> srctodst;
  srctodst[0] = 0;
  srctodst[1] = 1;
  srctodst[2] = 2;
  srctodst[3] = 3;
  int nxtidx = 4;
  ll nkey = 0;
  for(int i = 0; i < numSquares; i++) {
    int comp = (key >> (NUM_BITS * i)) & LOW_ORDER;
    if(comp == 0) continue;
    if(!srctodst.count(comp)) srctodst[comp] = nxtidx++;
    nkey |= ((ll)srctodst[comp]) << (NUM_BITS * i);
  }
  vector<int> cand(assignment.size());
  for(int i = 0; i < (int)assignment.size(); i++) {
    if(srctodst.count(i)) cand[srctodst[i]] = assignment[i];
    else cand[i] = assignment[i];
  }
  assert((int)cand.size() >= nxtidx);
  while((int)cand.size() > nxtidx) cand.pop_back();
  assignment.swap(cand);
  assert((int)assignment.size() >= 4);
  key = nkey;
}

vector<string> g;
map<ll, vector<vector<int>>> ndp;

void pillar(ll state, vector<vector<int>>& windowAssignments, int currrow, int currcol, int numCols) {
  assert(g[currrow][currcol] == '#');
  for(auto& assignment: windowAssignments) {
    vector<int> newassign = assignment;
    ll nstate = state;
    nstate <<= NUM_BITS;
    nstate &= (1LL << ((numCols) * NUM_BITS)) - 1;
    normalize(nstate, newassign, numCols);
    ndp[nstate].push_back(newassign);
  }
}

void addstore(ll state, vector<vector<int>>& windowAssignments, int currrow, int currcol, int numCols) {
  assert(g[currrow][currcol] == '.');
  for(auto& assignment: windowAssignments) {
    vector<int> newassign = assignment;
    if(currrow > 0) {
      int lhs = ((state >> (NUM_BITS * (numCols-1)))) & LOW_ORDER;
      if(lhs > 0 && g[currrow-1][currcol] == '.') newassign[lhs]++;
    }
    if(currcol > 0) {
      int lhs = state & LOW_ORDER;
      if(lhs > 0 && g[currrow][currcol-1] == '.') newassign[lhs]++;
    }
    ll nstate = state;
    nstate <<= NUM_BITS;
    nstate &= (1LL << ((numCols) * NUM_BITS)) - 1;
    normalize(nstate, newassign, numCols);
    ndp[nstate].push_back(newassign);
  }
}

void keepempty(ll state, vector<vector<int>>& windowAssignments, int currrow, int currcol, int numCols) {
  assert(g[currrow][currcol] != '#');
  for(auto& assignment: windowAssignments) {
    ll nstate = state;
    int nidx = (int)windowAssignments[0].size();
    vector<int> newassign = assignment;
    if(g[currrow][currcol] == 'U' || g[currrow][currcol] == 'D') {
      if(g[currrow][currcol] == 'U') nidx = 2;
      else nidx = 3;
    }
    else {
      int numwindows = 0;
      if(currrow > 0) {
        int lhs = ((state >> (NUM_BITS * (numCols-1)))) & LOW_ORDER;
        if(lhs == 0 && g[currrow-1][currcol] == '.') numwindows++;
      }
      if(currcol > 0) {
        int lhs = state & LOW_ORDER;
        if(lhs == 0 && g[currrow][currcol-1] == '.') numwindows++;
      }
      newassign.push_back(numwindows);
    }
    if(currrow > 0) {
      int lhs = ((state >> (NUM_BITS * (numCols-1)))) & LOW_ORDER;
      if(lhs > 0) mergeWindow(nidx, lhs, newassign, nstate, numCols);
    }
    if(currcol > 0) {
      int lhs = state & LOW_ORDER;
      if(lhs > 0) mergeWindow(nidx, lhs, newassign, nstate, numCols);
    }
    nstate <<= NUM_BITS;
    nstate |= nidx;
    nstate &= (1LL << (numCols * NUM_BITS)) - 1;
    normalize(nstate, newassign, numCols);
    ndp[nstate].push_back(newassign);
  }
}

map<ll, vector<vector<int>>> dp;
int ret;

int main() {
  {
    int r, c;
    cin >> r >> c;
    g.resize(r);
    for(int i = 0; i < r; i++) cin >> g[i];
    transpose(g);
  }
  int numCols = (int)g[0].size();
  {
    vector<vector<int>> gg;
    gg.push_back({0, 0, 0, 0});
    dp[0] = gg;
  }
  for(int i = 0; i < (int)g.size(); i++) {
    for(int j = 0; j < (int)g[i].size(); j++) {
      ndp.clear();
      for(auto& state: dp) {
        if(g[i][j] == '#') {
          pillar(state.first, state.second, i, j, numCols);
        }
        if(g[i][j] == '.') {
          addstore(state.first, state.second, i, j, numCols);
        }
        if(g[i][j] != '#') {
          keepempty(state.first, state.second, i, j, numCols);
        }
      }
      dp.swap(ndp);
      for(auto& state: dp) {
        cleanse(state.second);
        for(auto& cand: state.second) ret = max(ret, cand[1]);
      }
    }
  }
  cout << ret << "\n";
}