#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i, a, b) for (int i = (a); i < (int)(b); ++i)
#define rrep(i, a, b) for (int i = ((int)b) - 1; i >= (int)(a); --i)
#define all(c) c.begin(), c.end()
#define sz(c) ((int)c.size())
using pii = pair<int, int>;
using vi = vector<int>;
using vvi = vector<vi>;

struct UnionFind {
    vi data;
    int comp;
    UnionFind() {}
    UnionFind(int size) {
        init(size);
    }
    void init(int size) {
        data.assign(size, -1);
        comp = size;
    }
    void 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;
            comp--;
        }
    }
    bool same(int x, int y) {
        return root(x) == root(y);
    }
    int root(int x) {
        if (data[x] < 0) {
            return x;
        } else {
            return data[x] = root(data[x]);
        }
    }
    int size(int x) {
        return -data[root(x)];
    }
    int components() {
        return comp;
    }
};

vector<int> calc(const vector<string> &F) {
    int H = sz(F);
    int W = sz(F[0]);

    set<pii> st;
    rep(y, 0, H) {
        rep(x, 0, W) {
            if (F[y][x] == '#') {
                st.insert({x,     y    });
                st.insert({x + 1, y    });
                st.insert({x    , y + 1});
                st.insert({x + 1, y + 1});
            }
        }
    }
    int n = sz(st);
    map<pii, vector<pii>> mp;
    for (auto p : st) {
        int x, y;
        tie(x, y) = p;
        int g = __gcd(x, y);
        if (x == 0 && y == 0) {
            mp[{0, 0}].push_back({x, y});
        } else {
            mp[{x / g, y / g}].push_back({x, y});
        }
    }
    using T = tuple<int, int, vector<pii>>;
    vector<T> vec;
    for (auto p : mp) {
        int x, y;
        vector<pii> tmp;
        tie(x, y) = p.first;
        tmp = p.second;
        vec.push_back(make_tuple(x, y, tmp));
    }
    sort(all(vec), [](const T& l, const T &r) {
        int x1, y1, x2, y2;
        tie(x1, y1, ignore) = l;
        tie(x2, y2, ignore) = r;
        if (x1 == 0 && y1 == 0) return true;
        if (x2 == 0 && y2 == 0) return false;
        return x2 * y1 < x1 * y2;
    });
    
    int M = (H + 1) * (W + 1);
    vector<int> size;
    UnionFind uf(M);
    auto idx = [&](int x, int y) {
        return y * (W + 1) + x;
    };
    auto ok = [&](int x, int y) {
        return 0 <= x && x < W && 0 <= y && y < H && F[y][x] == '#';
    };
    // cerr << "n: " << n << endl;
    int cnt = 0;
    for (auto &u : vec) {
        int X, Y;
        vector<pii> w;
        tie(X, Y, w) = u;
        
        if (X == 0 && Y == 0) {
            uf.unite(idx(0, 0), idx(1, 0));
            cnt++;
            continue;
        }
        cnt += sz(w);

        // cerr << "X: " << X << ", Y: "  << Y << ", sz(w): " << sz(w) << ", cnt:" << cnt << endl;

        for (pii p : w) {
            int x, y;
            tie(x, y) = p;

            // cerr << "x: " << x << ", y: " << y << endl;

            if (ok(x - 1, y - 1) || ok(x, y - 1)) {
                // 下
                // cerr << "1: (" << x << ", " << y << ") <--> (" << x << ", " << y - 1 << ")" << endl;
                uf.unite(idx(x, y), idx(x, y - 1));
            }
            if (ok(x, y) || ok(x, y - 1)) {
                // 右
                // cerr << "2: (" << x << ", " << y << ") <--> (" << x + 1 << ", " << y << ")" << endl;
                uf.unite(idx(x, y), idx(x + 1, y));
            }
        }
        // cerr << sz(size)<< ":  uf.comp: " << uf.components() << " M-n:" << M - n << " n-cnt: " << n - cnt << " ==> push_back " << uf.components() - (M - n) - (n - cnt) << endl;
        size.push_back(uf.components() - (M - n) - (n - cnt));
    }
    return size;
}

signed main() {
    int H, W;
    cin >> H >> W;
    vector<string> F(H);
    rep(i, 0, H) {
        cin >> F[i];
    }
    reverse(all(F));

    auto size1 = calc(F);
    size1.insert(begin(size1), 0);
    
    // cerr << "size1: ";
    // for (int x : size1) {
        // cerr << x << " ";
    // }
    // cerr << endl;

    vector<string> G(W, string(H, '.'));
    rep(i, 0, H) {
        rep(j, 0, W) {
            G[j][i] = F[i][j];
        }
    }
    auto size2 = calc(G);
    reverse(all(size2));
    size2.push_back(0);

    // cerr << "size2: ";
    // for (int x : size2) {
        // cerr << x << " ";
    // }
    // cerr << endl;

    assert(sz(size1) == sz(size2));
    int ans = 0;
    rep(i, 0, sz(size1)) {
        // cerr << "sum " << i << ": " << size1[i] + size2[i] << endl;
        ans = max(ans, size1[i] + size2[i]);
    }
    cout << ans << endl;
}


Measured memory_bytes: 79756