10 10
.L.....R..
.........U
..D....D..
.R......L.
....L.....
.........D
......U...
D....R....
...U......
........L.
 5 5
DD..D
.....
LU...
U...U
.UL.U
 1 1
U
 5 5
UD..L
RRD..
..RDD
UUL..
DDLRR
 19 23
U..U..R........L...D...
.D.....UL.U.U........DR
..D.U..D....L......R...
D.......RL.L....D.....R
U..D.....U...U.L..D...U
...........L...........
U....U....D.U......LRR.
......RL...U...L.......
DLU..U......UU.U.U.D...
...........D....U......
U...DL......LL.....R...
...U..DD..........LD...
.R.........D.....UU...U
....D......R..........D
.L..........R.....L....
.R........L.LL....R....
..R...D........R....D..
.LR.R..LDU.DDRL......U.
...LL.....D.....DD.....
 11 29
URRUUDDLURLRDDLLRLDUDR.UDLLD.
LRRUDLUDLDULUDL.DURDRR.RRLLRR
D.DUDDURLRDDULDUDDUDDURRDLD.L
.RULURURRDLRRRLUUUU.RDLDLRRRL
.RLDDU.UUULUURURRLLUU.RLDRDUD
LRL.URRRDDURUURUDRRDLDDULRDRL
RLULDU.LRDUDRLDLRDDDDRUUDRDLL
DLUDURRDDUDLLDLLUURLDRUURRLUL
L.RRURRDDRRURRRDDUDRRDULR.LUR
LDLRULURRUULRDUUULLU.LLU.LLLL
DUURDULDDUDLRUUDRUULURLD.RL.U
 2 2
RD
UL
 1 10
LLLLLRRRRR
 3 3
...
...
..R
 17 13
...LD.UR.RUU.
LDLULDUDRRDRL
DD.RRLRUR.UD.
RU...D...LD..
.UR.R...URUUD
.RURD.RLR.D.R
.UUU.RU...UR.
UUUU.R.......
RL.LRU.UD.DUD
LD.DRURRLRDRL
.DR..UULUDDR.
LRLURRUUDDLUR
.LRDDLLR.L.DU
DRUDLLD.LRRU.
..DL.UDL.DUL.
U.DL..D..U.RD
RR.R...RL.L..

2 2
 4 1
 1 1
 8 3
 9 1
 94 1
 4 4
 5 2
 1 1
 24 2

#include <bits/stdc++.h>
using namespace std;
struct node {
  int I, J;
  int Key;
  node *Left;
  node *Right;
  node *Down;
  node *Up;
};
node **mas;
int **error;
int n, m;
void update();
bool NotNull(node N) {
  if (N.Key != -1) return true;
  return false;
};
bool NotNullKey(int Cell, int Key) {
  if (Cell != Key) return true;
  return false;
};
int getKey(int i, int j) { return i * m + j; };
void set_left(int iNode, int jNode, int iLink, int jLink) {
  if (iNode == -1 || jNode == -1) return;
  if (NotNull(mas[iNode][jNode]) && (iLink != -1 && jLink != -1))
    mas[iNode][jNode].Left = mas[iLink] + jLink;
};
void set_right(int iNode, int jNode, int iLink, int jLink) {
  if (iNode == -1 || jNode == -1) return;
  if (NotNull(mas[iNode][jNode]) && (iLink != -1 && jLink != -1))
    mas[iNode][jNode].Right = mas[iLink] + jLink;
};
void set_down(int iNode, int jNode, int iLink, int jLink) {
  if (iNode == -1 || jNode == -1) return;
  if (NotNull(mas[iNode][jNode]) && (iLink != -1 && jLink != -1))
    mas[iNode][jNode].Down = mas[iLink] + jLink;
};
void set_up(int iNode, int jNode, int iLink, int jLink) {
  if (iNode == -1 || jNode == -1) return;
  if (NotNull(mas[iNode][jNode]) && (iLink != -1 && jLink != -1))
    mas[iNode][jNode].Up = mas[iLink] + jLink;
};
node *getNext(node *Node, int Key) {
  node *Current;
  switch (Node->Key) {
    case 2:
      Current = Node->Down;
      while (Current != (node *)NULL) {
        if (NotNullKey(error[Current->I][Current->J], Key)) {
          return Current;
        } else {
          Current = Current->Down;
        }
      }
      return Current;
      break;
    case 3:
      Current = Node->Up;
      while (Current != (node *)NULL) {
        if (NotNullKey(error[Current->I][Current->J], Key)) {
          return Current;
        } else {
          Current = Current->Up;
        }
      }
      return Current;
      break;
    case 0:
      Current = Node->Right;
      while (Current != (node *)NULL) {
        if (NotNullKey(error[Current->I][Current->J], Key)) {
          return Current;
        } else {
          Current = Current->Right;
        }
      }
      return Current;
      break;
    case 1:
      Current = Node->Left;
      while (Current != (node *)NULL) {
        if (NotNullKey(error[Current->I][Current->J], Key)) {
          return Current;
        } else {
          Current = Current->Left;
        }
      }
      return Current;
      break;
    default:
      return (node *)NULL;
      break;
  }
  return (node *)NULL;
};
void solve(int &Max, int &Num) {
  Max = 0;
  Num = 0;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      int key = getKey(i, j);
      if (NotNull(mas[i][j])) {
        int temp = 0;
        node *Current = mas[i] + j;
        while (Current != (node *)NULL) {
          temp++;
          error[Current->I][Current->J] = key;
          node *Pred = Current;
          Current = getNext(Current, key);
          if (Current != (node *)NULL) {
            if (Pred->Left != (node *)NULL) Pred->Left->Right = Pred->Right;
            if (Pred->Right != (node *)NULL) Pred->Right->Left = Pred->Left;
            if (Pred->Down != (node *)NULL) Pred->Down->Up = Pred->Up;
            if (Pred->Up != (node *)NULL) Pred->Up->Down = Pred->Down;
          }
        }
        if (temp > Max) {
          Max = temp;
          Num = 1;
        } else {
          if (temp == Max) {
            Num++;
          }
        }
        update();
      } else if (Max == 0)
        Num++;
    }
  }
};
void update() {
  for (int i = 0; i < n; i++) {
    int iPred = -1, jPred = -1;
    int iCurrent = -1, jCurrent = -1;
    for (int j = 0; j < m; j++) {
      if (NotNull(mas[i][j])) {
        iPred = iCurrent;
        jPred = jCurrent;
        iCurrent = i;
        jCurrent = j;
        set_right(iPred, jPred, iCurrent, jCurrent);
        set_left(iCurrent, jCurrent, iPred, jPred);
      }
    }
  }
  for (int j = 0; j < m; j++) {
    int iPred = -1, jPred = -1;
    int iCurrent = -1, jCurrent = -1;
    for (int i = 0; i < n; i++) {
      if (NotNull(mas[i][j])) {
        iPred = iCurrent;
        jPred = jCurrent;
        iCurrent = i;
        jCurrent = j;
        set_down(iPred, jPred, iCurrent, jCurrent);
        set_up(iCurrent, jCurrent, iPred, jPred);
      }
    }
  }
}
int main() {
  scanf("%d %d", &n, &m);
  mas = (node **)calloc(n, sizeof(node *));
  error = (int **)calloc(n, sizeof(int *));
  for (int i = 0; i < n; i++) {
    mas[i] = (node *)calloc(m, sizeof(node));
    error[i] = (int *)calloc(m, sizeof(int));
  };
  for (int i = 0; i < n; i++) {
    char *str = new char[m + 2];
    scanf("%s", str);
    int len = strlen(str);
    for (int j = 0; j < len; j++) {
      error[i][j] = -1;
      mas[i][j].I = i;
      mas[i][j].J = j;
      mas[i][j].Left = NULL;
      mas[i][j].Right = NULL;
      mas[i][j].Down = NULL;
      mas[i][j].Up = NULL;
      switch (str[j]) {
        case 'R':
          mas[i][j].Key = 0;
          break;
        case 'L':
          mas[i][j].Key = 1;
          break;
        case 'D':
          mas[i][j].Key = 2;
          break;
        case 'U':
          mas[i][j].Key = 3;
          break;
        default:
          mas[i][j].Key = -1;
          break;
      }
    }
    delete[] str;
  }
  int Max, Num;
  update();
  solve(Max, Num);
  printf("%d %d\n", Max, Num);
  return 0;
}
