#define _USE_MATH_DEFINES
#include <stdio.h>
#include <iostream>
#include <string>
#include <vector>
#include <utility>
#include <algorithm>
#include <queue>
#include <list>
#include <stack>
#include <math.h>
#include <map>
#include <unordered_map>
#include <set>
using namespace std;

#define ll long long
#define ull unsigned long long

#define	max	1000000007

ll gcd(ll a, ll b) {
	if (a < b)
		swap(a, b);
	while (ll r = a % b)
		a = b, b = r;
	return b;
}

class mod
{
public:
	ll val;

	mod(ll v)
	{
		val = v % max;
	}

	mod()
	{
		val = 0;
	}

	void operator -=(const mod &v)
	{
		val -= v.val;

		if (val < 0)
			val += max;
	}

	void operator +=(const mod &v)
	{
		if (val + v.val >= max)
			val -= max;
		val += v.val;
	}

	void operator +=(ll &v)
	{
		if (val + v >= max)
			val -= max;
		val += v;
	}

	void operator *=(const mod &v)
	{
		val *= v.val;
		val %= max;
	}

	void operator *=(ll &v)
	{
		val *= v;
		val %= max;
	}

	ll modinv(ll a)
	{
		ll b = max, u = 1, v = 0;
		while (b)
		{
			ll t = a / b;
			a -= t * b; swap(a, b);
			u -= t * v; swap(u, v);
		}
		u %= max;
		if (u < 0)
			u += max;
		return u;
	}

	void operator /=(const mod &v)
	{
		val *= modinv(v.val);
		val %= max;
	}

	void operator /=(ll &v)
	{
		val *= modinv(v);
		val %= max;
	}
};

struct UnionFind
{
	vector<int> par; // par[i]:iの親の番号　(例) par[3] = 2 : 3の親が2
	vector<int> childN;
	ll r = 0;

	UnionFind(int N) : par(N), childN(N)
	{ 
		//最初は全てが根であるとして初期化
		for (int i = 0; i < N; i++) 
			par[i] = i, childN[i] = 1;
	}

	int root(int x) 
	{ 
		// データxが属する木の根を再帰で得る：root(x) = {xの木の根}
		if (par[x] == x) return x;
		return par[x] = root(par[x]);
	}

	void unite(int x, int y) 
	{
		// xとyの木を併合
		int rx = root(x); //xの根をrx
		int ry = root(y); //yの根をry
		if (rx == ry) return; //xとyの根が同じ(=同じ木にある)時はそのまま
		par[rx] = ry; //xとyの根が同じでない(=同じ木にない)時：xの根rxをyの根ryにつける
		r -= childN[rx] * (childN[rx] - 1) / 2;
		r -= childN[ry] * (childN[ry] - 1) / 2;
		childN[ry] += childN[rx];
		childN[rx] = 0;
		r += childN[ry] * (childN[ry] - 1) / 2;
	}

	bool same(int x, int y)
	{
		// 2つのデータx, yが属する木が同じならtrueを返す
		int rx = root(x);
		int ry = root(y);
		return rx == ry;
	}
};

//	for priority queue
//	priority_queue<ipair, vector<ipair>, greater<ipair>>
using ipair = pair<int, pair<int, int>>;
bool operator>(const ipair a, const ipair b) { return a.first > b.first; };
bool operator<(const ipair a, const ipair b) { return a.first < b.first; };

using xpair = pair<int, int>;
bool operator>(const xpair &a, const xpair &b) { return a.second > b.second || (a.second == b.second && a.first > b.first); };
bool operator<(const xpair &a, const xpair &b) { return a.second < b.second || (a.second == b.second && a.first > b.first); };
bool operator==(const xpair &a, const xpair &b) { return a.first== b.first; };

int main()
{
	int h, w;
	cin >> h >> w;
	vector<vector<bool>> s(h, vector<bool>(w, false));
	for (int i = 0; i < h; i++)
		for (int j = 0; j < w; j++)
		{
			char c;
			cin >> c;
			if (c == '#')
				s[i][j] = true;
		}

	vector<vector<pair<int, int>>> a(h + 1, vector<pair<int, int>>(w + 1, {0, 0}));
	
	for (int i = 1; i <= h; i++)
	{
		for (int j = 1; j <= w; j++)
		{
			if (s[i - 1][j - 1])
				a[i][j].first = 0;
			else
				a[i][j].first = a[i][j - 1].first + 1;
		}
		for (int j = w, k = w; k > 0; k--)
		{
			if (a[i][k].first == 0)
			{
				j = k - 1;
				continue;
			}
			a[i][k].first = a[i][j].first;
		}
	}
	for (int j = 1; j <= w; j++)
	{
		for (int i = 1; i <= h; i++)
		{
			if (s[i - 1][j - 1])
				a[i][j].second = 0;
			else
				a[i][j].second = a[i - 1][j].second + 1;
		}
		for (int i = h, k = h; k > 0; k--)
		{
			if (a[k][j].second == 0)
			{
				i = k - 1;
				continue;
			}
			a[k][j].second = a[i][j].second;
		}
	}

	int r = 0;
	for (int i = 1; i <= h; i++)
		for (int j = 1; j <= w; j++)
			if (r < a[i][j].first + a[i][j].second)
				r = a[i][j].first + a[i][j].second;
	printf("%d", --r);
	return 0;
}


Measured memory_bytes: 35036