import java.io.*;
import java.util.*;
/**
* Made by egor https://github.com/chermehdi/egor.
*
* @author Azuz
*
*/
public class Main {
private static final int BOT = 0, LEFT = 1, TOP = 2, RIGHT = 3;
private static final int VER = 0, HOR = 1;
int n, m, ans;
int size = 0;
char[][] arr;
boolean[][] vis;
boolean[][][] avis;
void solve(InputReader in, PrintWriter out) {
n = in.nextInt();
m = in.nextInt();
arr = new char[n][];
for (int i = 0; i < n; ++i) {
arr[i] = in.next().toCharArray();
}
UnionFind uf = new UnionFind(n, m);
// Add UF connectivity without considering mirrors
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) if (arr[i][j] == '.') {
// Vertical
if (i - 1 >= 0 && arr[i - 1][j] == '.') {
uf.union(i, j, VER, i - 1, j, VER);
}
// Horizontal
if (j - 1 >= 0 && arr[i][j - 1] == '.') {
uf.union(i, j, HOR, i, j - 1, HOR);
}
}
}
// Add UF using only mirrors
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) if (arr[i][j] == '/' || arr[i][j] == '\\'){
if (arr[i][j] == '/') { // / mirror
if (i + 1 < n && j + 1 < m) {
int x1 = i + 1, y1 = j, dir1 = BOT;
int x2 = i, y2 = j + 1, dir2 = RIGHT;
while (x1 >= 0 && y1 >= 0 && x1 < n && y1 < m && arr[x1][y1] != '.') {
if (x1 == i && y1 == j) break;
if (arr[x1][y1] == '#') break;
if (arr[x1][y1] == '/') {
if (dir1 == BOT) {y1--; dir1=LEFT;}
if (dir1 == TOP) {y1++; dir1=RIGHT;}
if (dir1 == LEFT) {x1++; dir1=BOT;}
if (dir1 == RIGHT) {x1--; dir1=TOP;}
} else if (arr[x1][y1] == '\\') {
if (dir1 == BOT) {++y1; dir1=RIGHT;}
if (dir1 == TOP) {--y1; dir1=LEFT;}
if (dir1 == RIGHT) {++x1; dir1=BOT;}
if (dir1 == LEFT) {--x1; dir1=TOP;}
}
}
while (x2 >= 0 && y2 >= 0 && x2 < n && y2 < m && arr[x2][y2] != '.') {
if (x2 == i && j == y2) break;
if (arr[x2][y2] == '#') break;
if (arr[x2][y2] == '/') {
if (dir2 == BOT) {y2--; dir2=LEFT;}
if (dir2 == TOP) {y2++; dir2=RIGHT;}
if (dir2 == LEFT) {x2++; dir2=BOT;}
if (dir2 == RIGHT) {x2--; dir2=TOP;}
} else if (arr[x2][y2] == '\\') {
if (dir2 == BOT) {++y2; dir2=RIGHT;}
if (dir2 == TOP) {--y2; dir2=LEFT;}
if (dir2 == RIGHT) {++x2; dir2=BOT;}
if (dir2 == LEFT) {--x2; dir2=TOP;}
}
}
int d1 = dir1 == LEFT || dir1 == RIGHT ? HOR : VER;
int d2 = dir2 == LEFT || dir2 == RIGHT ? HOR : VER;
if (x1 >= 0 && x1 < n && y1 < m && y1 >= 0 && x2 >= 0 && x2 < n && y2 >= 0 && y2 < m
&& arr[x1][y1] == '.' && arr[x2][y2] == '.') {
uf.union(x1, y1, d1, x2, y2, d2);
}
}
if (i - 1 < n && j - 1 < m) {
int x1 = i - 1, y1 = j, dir1 = TOP;
int x2 = i, y2 = j - 1, dir2 = LEFT;
while (x1 >= 0 && y1 >= 0 && x1 < n && y1 < m && arr[x1][y1] != '.') {
if (x1 == i && y1 == j) break;
if (arr[x1][y1] == '#') break;
if (arr[x1][y1] == '/') {
if (dir1 == BOT) {y1--; dir1=LEFT;}
if (dir1 == TOP) {y1++; dir1=RIGHT;}
if (dir1 == LEFT) {x1++; dir1=BOT;}
if (dir1 == RIGHT) {x1--; dir1=TOP;}
} else if (arr[x1][y1] == '\\') {
if (dir1 == BOT) {++y1; dir1=RIGHT;}
if (dir1 == TOP) {--y1; dir1=LEFT;}
if (dir1 == RIGHT) {++x1; dir1=BOT;}
if (dir1 == LEFT) {--x1; dir1=TOP;}
}
}
while (x2 >= 0 && y2 >= 0 && x2 < n && y2 < m && arr[x2][y2] != '.') {
if (x2 == i && j == y2) break;
if (arr[x2][y2] == '#') break;
if (arr[x2][y2] == '/') {
if (dir2 == BOT) {y2--; dir2=LEFT;}
if (dir2 == TOP) {y2++; dir2=RIGHT;}
if (dir2 == LEFT) {x2++; dir2=BOT;}
if (dir2 == RIGHT) {x2--; dir2=TOP;}
} else if (arr[x2][y2] == '\\') {
if (dir2 == BOT) {++y2; dir2=RIGHT;}
if (dir2 == TOP) {--y2; dir2=LEFT;}
if (dir2 == RIGHT) {++x2; dir2=BOT;}
if (dir2 == LEFT) {--x2; dir2=TOP;}
}
}
int d1 = dir1 == LEFT || dir1 == RIGHT ? HOR : VER;
int d2 = dir2 == LEFT || dir2 == RIGHT ? HOR : VER;
if (i == 15 && j == 4)
System.err.println(x1 + " " + y1 + "..." + x2 + " " + y2);
if (x1 >= 0 && x1 < n && y1 < m && y1 >= 0 && x2 >= 0 && x2 < n && y2 >= 0 && y2 < m
&& arr[x1][y1] == '.' && arr[x2][y2] == '.') {
uf.union(x1, y1, d1, x2, y2, d2);
}
}
} else { // \ Mirror
if (i - 1 < n && j + 1 < m) {
int x1 = i - 1, y1 = j, dir1 = TOP;
int x2 = i, y2 = j + 1, dir2 = RIGHT;
while (x1 >= 0 && y1 >= 0 && x1 < n && y1 < m && arr[x1][y1] != '.') {
if (x1 == i && y1 == j) break;
if (arr[x1][y1] == '#') break;
if (arr[x1][y1] == '/') {
if (dir1 == BOT) {y1--; dir1=LEFT;}
if (dir1 == TOP) {y1++; dir1=RIGHT;}
if (dir1 == LEFT) {x1++; dir1=BOT;}
if (dir1 == RIGHT) {x1--; dir1=TOP;}
} else if (arr[x1][y1] == '\\') {
if (dir1 == BOT) {++y1; dir1=RIGHT;}
if (dir1 == TOP) {--y1; dir1=LEFT;}
if (dir1 == RIGHT) {++x1; dir1=BOT;}
if (dir1 == LEFT) {--x1; dir1=TOP;}
}
}
while (x2 >= 0 && y2 >= 0 && x2 < n && y2 < m && arr[x2][y2] != '.') {
if (x2 == i && j == y2) break;
if (arr[x2][y2] == '#') break;
if (arr[x2][y2] == '/') {
if (dir2 == BOT) {y2--; dir2=LEFT;}
if (dir2 == TOP) {y2++; dir2=RIGHT;}
if (dir2 == LEFT) {x2++; dir2=BOT;}
if (dir2 == RIGHT) {x2--; dir2=TOP;}
} else if (arr[x2][y2] == '\\') {
if (dir2 == BOT) {++y2; dir2=RIGHT;}
if (dir2 == TOP) {--y2; dir2=LEFT;}
if (dir2 == RIGHT) {++x2; dir2=BOT;}
if (dir2 == LEFT) {--x2; dir2=TOP;}
}
}
int d1 = dir1 == LEFT || dir1 == RIGHT ? HOR : VER;
int d2 = dir2 == LEFT || dir2 == RIGHT ? HOR : VER;
if (x1 >= 0 && x1 < n && y1 < m && y1 >= 0 && x2 >= 0 && x2 < n && y2 >= 0 && y2 < m
&& arr[x1][y1] == '.' && arr[x2][y2] == '.') {
uf.union(x1, y1, d1, x2, y2, d2);
}
}
if (i + 1 < n && j - 1 < m) {
int x1 = i + 1, y1 = j, dir1 = BOT;
int x2 = i, y2 = j - 1, dir2 = LEFT;
while (x1 >= 0 && y1 >= 0 && x1 < n && y1 < m && arr[x1][y1] != '.') {
if (x1 == i && y1 == j) break;
if (arr[x1][y1] == '#') break;
if (arr[x1][y1] == '/') {
if (dir1 == BOT) {y1--; dir1=LEFT;}
if (dir1 == TOP) {y1++; dir1=RIGHT;}
if (dir1 == LEFT) {x1++; dir1=BOT;}
if (dir1 == RIGHT) {x1--; dir1=TOP;}
} else if (arr[x1][y1] == '\\') {
if (dir1 == BOT) {++y1; dir1=RIGHT;}
if (dir1 == TOP) {--y1; dir1=LEFT;}
if (dir1 == RIGHT) {++x1; dir1=BOT;}
if (dir1 == LEFT) {--x1; dir1=TOP;}
}
}
while (x2 >= 0 && y2 >= 0 && x2 < n && y2 < m && arr[x2][y2] != '.') {
if (x2 == i && j == y2) break;
if (arr[x2][y2] == '#') break;
if (arr[x2][y2] == '/') {
if (dir2 == BOT) {y2--; dir2=LEFT;}
if (dir2 == TOP) {y2++; dir2=RIGHT;}
if (dir2 == LEFT) {x2++; dir2=BOT;}
if (dir2 == RIGHT) {x2--; dir2=TOP;}
} else if (arr[x2][y2] == '\\') {
if (dir2 == BOT) {++y2; dir2=RIGHT;}
if (dir2 == TOP) {--y2; dir2=LEFT;}
if (dir2 == RIGHT) {++x2; dir2=BOT;}
if (dir2 == LEFT) {--x2; dir2=TOP;}
}
}
int d1 = dir1 == LEFT || dir1 == RIGHT ? HOR : VER;
int d2 = dir2 == LEFT || dir2 == RIGHT ? HOR : VER;
if (x1 >= 0 && x1 < n && y1 < m && y1 >= 0 && x2 >= 0 && x2 < n && y2 >= 0 && y2 < m
&& arr[x1][y1] == '.' && arr[x2][y2] == '.') {
uf.union(x1, y1, d1, x2, y2, d2);
}
}
}
}
}
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
int a = uf.find(i, j, VER);
int b = uf.find(i, j, HOR);
if (a == b) { // Exception
uf.reduce(a, b);
}
}
}/*
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
System.err.print(uf.size(i, j, VER) + "/" + uf.size(i, j, HOR) + " ");
} System.err.println();
}*/
int max = -1;
int maxi = -1;
int maxj = -1;
PriorityQueue<Tuple> q = new PriorityQueue<>();
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) if (arr[i][j] == '.') {
int x = 0;
if (uf.find(i, j, 0) == uf.find(i, j, 1)) {
x = uf.size(i, j, 0);
} else {
x = uf.size(i, j) - 1;
}
q.offer(new Tuple(i, j, x));
if (q.size() > 100) {
q.poll();
}
}
}
// System.err.println(maxi + " " + maxj + " " + max);
// Simulate
ans = 0;
while (!q.isEmpty()) {
vis = new boolean[n][m];
avis = new boolean[n][m][4];
size = 0;
Tuple t = q.poll();
for (int dir = 0; dir < 4; ++dir) {
dfs(t.i, t.j, dir);
}
ans = Math.max(ans, size);
}
out.println(ans );
}
private static class Tuple implements Comparable<Tuple> {
int i, j, val;
public Tuple(int i, int j, int val) {
this.i = i;
this.j = j;
this.val = val;
}
@Override
public int compareTo(Tuple t) {
return Integer.compare(t.val, this.val);
}
}
private void dfs(int i, int j, int dir) {
if (i < 0 || j < 0) return ;
if (i >= n || j >= m) return ;
if (arr[i][j] == '#') return ;
if (avis[i][j][dir]) return ;
if (!vis[i][j] && arr[i][j] == '.') ++size;
avis[i][j][dir] = true;
vis[i][j] = true;
// System.err.println(i + " " + j + " > " + dir);
if (arr[i][j] == '.') {
if (dir == BOT) dfs(i + 1, j, dir);
if (dir == TOP) dfs(i - 1, j, dir);
if (dir == RIGHT) dfs(i, j + 1, dir);
if (dir == LEFT) dfs(i, j - 1, dir);
} else if (arr[i][j] == '/') {
if (dir == BOT) dfs(i, j - 1, LEFT);
if (dir == TOP) dfs(i, j + 1, RIGHT);
if (dir == LEFT) dfs(i + 1, j, BOT);
if (dir == RIGHT) dfs(i - 1, j, TOP);
} else { // \
if (dir == BOT) dfs(i, j + 1, RIGHT);
if (dir == TOP) dfs(i, j - 1, LEFT);
if (dir == RIGHT) dfs(i + 1, j, BOT);
if (dir == LEFT) dfs(i - 1, j, TOP);
}
}
public static void main(String[] args) {
InputReader in = new InputReader(System.in);
try (PrintWriter out = new PrintWriter(System.out)) {
new Main().solve(in, out);
}
}
}
class UnionFind {
int[] p, size;
int n, m;
int max_size;
public UnionFind(int n, int m) {
this.n = n;
this.m = m;
this.max_size = this.encode(n, m, 1) + 1;
size = new int[max_size];
p = new int[max_size];
for (int dir = 0; dir < 2; ++dir) {
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
int code = encode(i, j, dir);
p[code] = code;
size[code] = 1;
}
}
}
}
public int size(int i, int j, int dir) {
int code = encode(i, j, dir);
return size[find(code)];
}
public int size(int i, int j) {
return size(i, j, 0) + size(i, j, 1);
}
private void union(int u, int v) {
int x = find(u);
int y = find(v);
if (x == y) return ;
if (size[x] > size[y]) {
size[x] += size[y];
p[y] = x;
} else {
size[y] += size[x];
p[x] = p[y];
}
}
public void union(int i, int j, int dirij, int x, int y, int dirxy) {
int codeij = encode(i, j, dirij);
int codexy = encode(x, y, dirxy);
union(codeij, codexy);
}
public void reduce(int c1, int c2) {
if (size[c1] > c2) {
size[c1]--;
} else {
size[c2]--;
}
}
public int find(int i, int j, int dir) {
int code = encode(i, j, dir);
return find(code);
}
private int find(int code) {
if (p[code] == code) return code;
return p[code] = find(p[code]);
}
private int encode(int i, int j, int dir) {
int ret = (dir * this.n * this.m) + (i * this.m) + j;
return ret;
}
}
class InputReader {
private InputStream stream;
private static final int DEFAULT_BUFFER_SIZE = 1 << 16;
private static final int EOF = -1;
private byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
private int curChar;
private int numChars;
public InputReader(InputStream stream) {
this.stream = stream;
}
public int[] readIntArray(int tokens) {
int[] ret = new int[tokens];
for (int i = 0; i < tokens; i++) {
ret[i] = nextInt();
}
return ret;
}
public int read() {
if (this.numChars == EOF) {
throw new UnknownError();
} else {
if (this.curChar >= this.numChars) {
this.curChar = 0;
try {
this.numChars = this.stream.read(this.buf);
} catch (IOException ex) {
throw new InputMismatchException();
}
if (this.numChars <= 0) {
return EOF;
}
}
return this.buf[this.curChar++];
}
}
public int nextInt() {
int c;
for (c = this.read(); isSpaceChar(c); c = this.read()) {
}
byte sgn = 1;
if (c == 45) {
sgn = -1;
c = this.read();
}
int res = 0;
while (c >= 48 && c <= 57) {
res *= 10;
res += c - 48;
c = this.read();
if (isSpaceChar(c)) {
return res * sgn;
}
}
throw new InputMismatchException();
}
public long nextLong() {
int c;
for (c = this.read(); isSpaceChar(c); c = this.read()) {
}
byte sgn = 1;
if (c == 45) {
sgn = -1;
c = this.read();
}
long res = 0;
while (c >= 48 && c <= 57) {
res *= 10L;
res += c - 48;
c = this.read();
if (isSpaceChar(c)) {
return res * sgn;
}
}
throw new InputMismatchException();
}
public double nextDouble() {
double ret = 0, div = 1;
int c = read();
while (c <= ' ') {
c = read();
}
boolean neg = (c == '-');
if (neg) {
c = read();
}
do {
ret = ret * 10 + c - '0';
}
while ((c = read()) >= '0' && c <= '9');
if (c == '.') {
while ((c = read()) >= '0' && c <= '9') {
ret += (c - '0') / (div *= 10);
}
}
if (neg) {
return -ret;
}
return ret;
}
public String next() {
int c;
while (isSpaceChar(c = this.read())) {
}
StringBuilder result = new StringBuilder();
result.appendCodePoint(c);
while (!isSpaceChar(c = this.read())) {
result.appendCodePoint(c);
}
return result.toString();
}
public String nextLine() {
int c;
StringBuilder result = new StringBuilder();
boolean read = false;
while ((c = this.read()) != '\n') {
if (c == -1) {
return null;
}
result.appendCodePoint(c);
read = true;
}
if (!read) {
return null;
}
return result.toString();
}
public static boolean isSpaceChar(int c) {
return c == 32 || c == 10 || c == 13 || c == 9 || c == EOF;
}
public int[] nextIntArray(int n) {
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = nextInt();
}
return arr;
}
public long[] nextLongArray(int n) {
long[] arr = new long[n];
for (int i = 0; i < n; i++) {
arr[i] = nextLong();
}
return arr;
}
public int[][] nextIntMatrix(int n, int m) {
int[][] arr = new int[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
arr[i][j] = nextInt();
}
}
return arr;
}
public long[][] nextLongMatrix(int n, int m) {
long[][] arr = new long[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
arr[i][j] = nextLong();
}
}
return arr;
}
public char[] nextCharArray() {
return next().toCharArray();
}
public double[] nextDoubleArray(int n) {
double[] ret = new double[n];
for (int i = 0; i < n; i++) {
ret[i] = nextDouble();
}
return ret;
}
public int[]
nextIntArrayOneBased(int n) {
int[] ret = new int[n + 1];
for (int i = 1; i <= n; i++) {
ret[i] = nextInt();
}
return ret;
}
public char[][] nextCharMatrix(int n, int m) {
char[][] res = new char[n][m];
for (int i = 0; i < n; ++i) {
res[i] = nextCharArray();
}
return res;
}
}
Copy