// Original C++ solution (slower):
#include <bits/stdc++.h>

using namespace std;



#define ALL(a) begin(a), end(a)

#define TPL template

#define TNM typename



using ll = long long;

using ull = unsigned long long;



TPL<TNM T> using vec = vector<T>;

TPL<TNM T> using vec2 = vec<vec<T>>;

TPL<TNM T> using vec3 = vec<vec2<T>>;

TPL<TNM T> using vec4 = vec<vec3<T>>;

TPL<TNM T> using vec5 = vec<vec4<T>>;



TPL<TNM T> inline istream& operator >> (istream& is, vector<T>& vec) { for (T& x : vec) is >> x; return is; }

TPL<TNM V, TNM H> void resize(vector<V>& _v, const H _h) { _v.resize(_h); }

TPL<TNM V, TNM H, TNM ... T> void resize(vector<V>& _v, const H& _h, const T& ... _t) { _v.resize(_h); for (auto& __v : _v) resize(__v, _t ...); }

TPL<TNM V, TNM T> TNM enable_if<!is_class<V>::value>::type fill(vector<V>& _v, const T &_t) { std::fill(ALL(_v), _t); }

TPL<TNM V, TNM T> TNM enable_if<is_class<V>::value>::type fill(vector<V>& _v, const T &_t) { for (auto &_e : _v) fill(_e, _t); }

TPL<TNM T> inline void UNIQUE(vector<T>& _v) { sort(ALL(_v)); _v.erase(unique(ALL(_v)), _v.end()); }

struct pre_ { pre_() { cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(6); } } pre__;



const char O = '#';

const char F = '.';



struct UnionFind {

	vector<int> data;

	UnionFind() {};

	UnionFind(int size) : data(size, -1) { }

	bool unionSet(int x, int y) {

		x = root(x); y = root(y);

		if (x != y) {

			if (data[y] < data[x]) swap(x, y);

			data[x] += data[y]; data[y] = x;

		}

		return x != y;

	}

	bool findSet(int x, int y) {

		return root(x) == root(y);

	}

	int root(int x) {

		return data[x] < 0 ? x : data[x] = root(data[x]);

	}

	int size(int x) {

		return -data[root(x)];

	}

};



int main(void) {

	int H, W;

	cin >> H >> W;

	vec<string> MAP;

	resize(MAP, H);



	for (int i = 0; i < H; ++i) {

		cin >> MAP[i];

	}



	vec<UnionFind> uW(H, UnionFind(2000 + 1));

	vec<UnionFind> uH(W, UnionFind(2000 + 1));

	for (int i = 0; i < H; ++i) {

		for (int j = 0; j < W - 1; ++j) {

			if (MAP[i][j] == F && MAP[i][j + 1] == F) {

				uW[i].unionSet(j, j + 1);

			}

		}

	}



	for (int j = 0; j < W; ++j) {

		for (int i = 0; i < H - 1; ++i) {

			if (MAP[i][j] == F && MAP[i + 1][j] == F) {

				uH[j].unionSet(i, i + 1);

			}

		}

	}



	int ans = 0;

	for (int i = 0; i < H; ++i) {

		for (int j = 0; j < W; ++j) {

			int sum = uH[j].size(i) + uW[i].size(j);

			ans = max(ans, sum);

		}

	}



	cout << ans - 1 << endl;

	return 0;



}

// Optimized solution to the same problem (faster):
#include <bits/stdc++.h>

using namespace std;



#define ALL(a) begin(a), end(a)

#define TPL template

#define TNM typename



using ll = long long;

using ull = unsigned long long;



TPL<TNM T> using vec = vector<T>;

TPL<TNM T> using vec2 = vec<vec<T>>;

TPL<TNM T> using vec3 = vec<vec2<T>>;

TPL<TNM T> using vec4 = vec<vec3<T>>;

TPL<TNM T> using vec5 = vec<vec4<T>>;



TPL<TNM T> inline istream& operator >> (istream& is, vector<T>& vec) { for (T& x : vec) is >> x; return is; }

TPL<TNM V, TNM H> void resize(vector<V>& _v, const H _h) { _v.resize(_h); }

TPL<TNM V, TNM H, TNM ... T> void resize(vector<V>& _v, const H& _h, const T& ... _t) { _v.resize(_h); for (auto& __v : _v) resize(__v, _t ...); }

TPL<TNM V, TNM T> TNM enable_if<!is_class<V>::value>::type fill(vector<V>& _v, const T &_t) { std::fill(ALL(_v), _t); }

TPL<TNM V, TNM T> TNM enable_if<is_class<V>::value>::type fill(vector<V>& _v, const T &_t) { for (auto &_e : _v) fill(_e, _t); }

TPL<TNM T> inline void UNIQUE(vector<T>& _v) { sort(ALL(_v)); _v.erase(unique(ALL(_v)), _v.end()); }

struct pre_ { pre_() { cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(6); } } pre__;



const char O = '#';

const char F = '.';



struct UnionFind {

	vector<int> data;

	UnionFind(int size) : data(size, -1) { }

	bool unite(int x, int y) {

		x = root(x); y = root(y);

		if (x != y) {

			if (data[y] < data[x]) swap(x, y);

			data[x] += data[y]; data[y] = x;

		}

		return x != y;

	}

	bool same(int x, int y) {

		return root(x) == root(y);

	}

	int root(int x) {

		return data[x] < 0 ? x : data[x] = root(data[x]);

	}

	int size(int x) {

		return -data[root(x)];

	}

};





int main(void) {

	int H, W;

	cin >> H >> W;

	vec<string> MAP;

	resize(MAP, H);



	for (int i = 0; i < H; ++i) {

		cin >> MAP[i];

	}



	vec<UnionFind> uW(H, UnionFind(W));

	vec<UnionFind> uH(W, UnionFind(H));

	for (int i = 0; i < H; ++i) {

		for (int j = 0; j < W - 1; ++j) {

			if (MAP[i][j] == F && MAP[i][j + 1] == F) {

				uW[i].unite(j, j + 1);

			}

		}

	}



	for (int j = 0; j < W; ++j) {

		for (int i = 0; i < H - 1; ++i) {

			if (MAP[i][j] == F && MAP[i + 1][j] == F) {

				uH[j].unite(i, i + 1);

			}

		}

	}



	int ans = 0;

	for (int i = 0; i < H; ++i) {

		for (int j = 0; j < W; ++j) {

			int sum = uH[j].size(i) + uW[i].size(j);

			ans = max(ans, sum);

		}

	}



	cout << ans - 1 << endl;

	return 0;



}

// Fastest known solution for this problem: