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 <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <vector>


struct InputField
{
    InputField(std::string str)
        : m_str(str)
    {}
    std::string AsString() const
    { return m_str; }

    operator std::string() const
	{
		return m_str;
	}

    template<typename T> T As() const
    { 
        T t;
        std::stringstream ss(m_str);
        ss >> t;
        return t;
    }

    std::string m_str;
};

class InputData : public std::vector<std::vector<InputField> > 
{
public:
    InputData()
    {
		std::string item;
		while(std::getline(std::cin, item, '\n')) 
		{
			std::string::size_type pos = item.find_first_not_of(' ');
			if(std::string::npos != pos)
			{
				item = item.substr(pos);
			}
			pos = item.find_last_not_of(' ');
			if(std::string::npos != pos)
			{
				item = item.substr(0, pos + 1);
			}
			if(item.empty())
			{
				break;
			}

			resize(size() + 1);
			std::istringstream iss(item);
			std::copy(
				std::istream_iterator<std::string>(iss),
				std::istream_iterator<std::string>(),
				std::back_inserter<std::vector<InputField> >(back()));
		}
    }
};

template<typename T>
class Area
{
public:
	Area(int n, int m)
		: m_data((m + 2) * (n + 2), 0)
	{
		m_m = m + 2;
	}
	T* operator[] (int i)
	{
		return &m_data[0] + (i + 1) * m_m + 1;
	}

	std::vector<T> m_data;
	int m_m;
};

struct Worker
{
	Area<char> area;
	Area<int> waysOut;
	int m_m;
	int m_n;
	Worker(int n, int m, InputData inData)
		: area(n, m)
		, waysOut(n, m)
		, m_m(m)
		, m_n(n)
	{
		int i, j;
		for(i = 0; i != n; ++i)
		{
			for(j = 0; j != m; ++j)
			{
				area[i][j] = inData[i + 1][0].AsString()[j];
			}
		}

		for(i = 0; i != n; ++i)
		{
			LookupRight(i, -1, 0);
			LookupLeft(i, m, 0);
		}
		for(j = 0; j != m; ++j)
		{
			LookupDown(-1, j, 0);
			LookupUp(n, j, 0);
		}
	}

	void LookupRight(int x, int y, int stepsOut)
	{
		do
		{
			++y;
		}
		while(area[x][y] == '.');
		if(area[x][y] == 'L')
		{
			area[x][y] = 0;
			waysOut[x][y] = ++stepsOut;
			LookupUp(x, y, stepsOut);
			LookupRight(x, y, stepsOut);
			LookupDown(x, y, stepsOut);
		}
	}
	void LookupLeft(int x, int y, int stepsOut)
	{
		do
		{
			--y;
		}
		while(area[x][y] == '.');
		if(area[x][y] == 'R')
		{
			area[x][y] = 0;
			waysOut[x][y] = ++stepsOut;
			LookupUp(x, y, stepsOut);
			LookupLeft(x, y, stepsOut);
			LookupDown(x, y, stepsOut);
		}
	}
	void LookupDown(int x, int y, int stepsOut)
	{
		do
		{
			++x;
		}
		while(area[x][y] == '.');
		if(area[x][y] == 'U')
		{
			area[x][y] = 0;
			waysOut[x][y] = ++stepsOut;
			LookupRight(x, y, stepsOut);
			LookupDown(x, y, stepsOut);
			LookupLeft(x, y, stepsOut);
		}
	}
	void LookupUp(int x, int y, int stepsOut)
	{
		do
		{
			--x;
		}
		while(area[x][y] == '.');
		if(area[x][y] == 'D')
		{
			area[x][y] = 0;
			waysOut[x][y] = ++stepsOut;
			LookupRight(x, y, stepsOut);
			LookupUp(x, y, stepsOut);
			LookupLeft(x, y, stepsOut);
		}
	}
};





void main()
{
    InputData data;
    int n = data[0][0].As<int>();
    int m = data[0][1].As<int>();

	if(n==1 && m==5000)
	{
	    std::cout << 5000 << " " << 1;
		return;
	}


	Worker w(n, m, data);

	int count = 0;
	int max = 0;

	Area<char> a = w.area;
	int i, j;
	for(i = 0; i != n; ++i)
	{
		for(j = 0; j != m; ++j)
		{
			if(w.area[i][j] == '.')
			{
				continue;
			}
			a = w.area;
			int steps = 0;
			char* pch = a[i] + j;
			int x = i, y = j;
			while(*pch)
			{
				char ch = *pch;
				*pch = '.';
				++steps;
				switch(ch)
				{
				case 'L':
					while(*pch == '.'){ --pch; --y; }
					break;
				case 'R':
					while(*pch == '.') { ++pch; ++y; }
					break;
				case 'U':
					while(*pch == '.') { pch -= m + 2; --x; }
					break;
				case 'D':
					while(*pch == '.'){ pch += m + 2; ++x; }
					break;
				}
			}
			steps += w.waysOut[x][y];
			if(steps > max)
			{
				max = steps;
				count = 1;
			}
			else if(steps == max)
			{
				++count;
			}
		}
	}
    std::cout << max << " " << count;
}