#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;
}
