#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 mergeWindow(int& x, int y, ll& state, int numCols) {
  if(x == y) return;
  assert(x != y);
  assert(x > 0 && y > 0);
  if(x > y) swap(x, y);
  if(x == 2 && y == 3) {
    x = 1;
    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 {
    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, int numSquares) {
  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);
  }
  key = nkey;
}

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

void pillar(ll state, int currAmt, int currrow, int currcol, int numCols) {
  assert(g[currrow][currcol] == '#');
  {
    int topItem = (state >> (NUM_BITS * (numCols-1)));
    if(topItem > 1) {
      bool present = false;
      for(int i = 0; i < numCols-1 && !present; i++) {
        int otherItem = (state >> (NUM_BITS * i)) & LOW_ORDER;
        present = topItem == otherItem;
      }
      if(!present) return;
    }
  }
  ll nstate = state;
  nstate <<= NUM_BITS;
  nstate &= (1LL << ((numCols) * NUM_BITS)) - 1;
  normalize(nstate, numCols);
  ndp[nstate] = max(ndp[nstate], currAmt);
}

void addstore(ll state, int currAmt, int currrow, int currcol, int numCols) {
  assert(g[currrow][currcol] == '.');
  {
    int topItem = (state >> (NUM_BITS * (numCols-1)));
    if(topItem > 0) {
      bool present = false;
      for(int i = 0; i < numCols-1 && !present; i++) {
        int otherItem = (state >> (NUM_BITS * i)) & LOW_ORDER;
        present = topItem == otherItem;
      }
      if(!present) return;
    }
  }
  if(currrow > 0) {
    int lhs = ((state >> (NUM_BITS * (numCols-1)))) & LOW_ORDER;
    if(lhs > 0 && g[currrow-1][currcol] == '.') currAmt++;
  }
  if(currcol > 0) {
    int lhs = state & LOW_ORDER;
    if(lhs > 0 && g[currrow][currcol-1] == '.') currAmt++;
  }
  ll nstate = state;
  nstate <<= NUM_BITS;
  nstate &= (1LL << ((numCols) * NUM_BITS)) - 1;
  normalize(nstate, numCols);
  ndp[nstate] = max(ndp[nstate], currAmt);
}

void keepempty(ll state, int currAmt, int currrow, int currcol, int numCols) {
  assert(g[currrow][currcol] != '#');
  ll nstate = state;
  int nidx = LOW_ORDER;
  if(g[currrow][currcol] == 'U' || g[currrow][currcol] == 'D') {
    if(g[currrow][currcol] == 'U') nidx = 2;
    else nidx = 3;
  }
  else {
    if(currrow > 0) {
      int lhs = ((state >> (NUM_BITS * (numCols-1)))) & LOW_ORDER;
      if(lhs == 0 && g[currrow-1][currcol] == '.') currAmt++;
    }
    if(currcol > 0) {
      int lhs = state & LOW_ORDER;
      if(lhs == 0 && g[currrow][currcol-1] == '.') currAmt++;
    }
  }
  if(currrow > 0) {
    int lhs = ((state >> (NUM_BITS * (numCols-1)))) & LOW_ORDER;
    if(lhs > 0) mergeWindow(nidx, lhs, nstate, numCols);
  }
  if(currcol > 0) {
    int lhs = state & LOW_ORDER;
    if(lhs > 0) mergeWindow(nidx, lhs, nstate, numCols);
  }
  nstate <<= NUM_BITS;
  nstate |= nidx;
  nstate &= (1LL << (numCols * NUM_BITS)) - 1;
  normalize(nstate, numCols);
  ndp[nstate] = max(ndp[nstate], currAmt);
}

map<ll, 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();
  {
    dp[0] = 0;
  }
  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) {
        bool allOne = true;
        if(state.second <= ret) continue;
        for(int i = 0; i < numCols; i++) {
          int curr = (state.first >> (NUM_BITS * i)) & LOW_ORDER;
          if(curr == 0) continue;
          allOne &= curr == 1;
        }
        if(allOne) ret = state.second;
      }
    }
  }
  cout << ret << "\n";
}