import java.io.*;
import java.util.*;

public class SolveB_2 {
	String fileName = "robots";

	boolean isCapital(char c) {
		return (c >= 'A' && c <= 'Z');
	}

	int[][] toX;
	int[][] toY;
	int[][] color;
	int[] robotsInColor;
	int[] circlesInColor;
	boolean[][] hasRobot;

	class Point {
		int x;
		int y;

		public Point(int y, int x) {
			super();
			this.x = x;
			this.y = y;
		}

		@Override
		public String toString() {
			return "Point [x=" + x + ", y=" + y + "]";
		}

	}

	public void solve() throws IOException {
		int n = nextInt();
		int m = nextInt();
		int G = nextInt();
		hasRobot = new boolean[n][m];
		toX = new int[n][m];
		toY = new int[n][m];
		@SuppressWarnings("unchecked")
		ArrayList<Point>[][] g = new ArrayList[n][m];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				g[i][j] = new ArrayList<>();
			}
		}

		for (int i = 0; i < n; i++) {
			String s = nextToken();
			for (int j = 0; j < m; j++) {
				char c = s.charAt(j);
				
				if (isCapital(c)) {
					hasRobot[i][j] = true;
					c = (char) (c - 'A' + 'a');
				} 
				
				if (c == 's') {
					toX[i][j] = j;
					toY[i][j] = i + 1;
				} else if (c == 'n') {
					toX[i][j] = j;
					toY[i][j] = i - 1;
				} else if (c == 'e') {
					toX[i][j] = j + 1;
					toY[i][j] = i;
				} else if (c == 'w') {
					toX[i][j] = j - 1;
					toY[i][j] = i;
				} else {
					throw new Error();
				}
				g[i][j].add(new Point(toY[i][j], toX[i][j]));
				g[toY[i][j]][toX[i][j]].add(new Point(i, j));
			} //
		}

		robotsInColor = new int[n * m];
		circlesInColor = new int[n * m];

		color = new int[n][m];
		int currentColor = 1;
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				if (color[i][j] == 0) {
					ret = false;
					dfs(i, j, currentColor++, g);
					circleDFS(i, j, new boolean[1001][1001]);
				}
			}
		}
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				if (hasRobot[i][j]) {
					robotsInColor[color[i][j]]++;
				}
			}
		}
		long ans = 0;
		for (int i = 0; i < n * m; i++) {
			if (robotsInColor[i] < circlesInColor[i]) {
				ans += robotsInColor[i];
			} else {
				ans += circlesInColor[i];
			}
		}
		out.println(ans);
	}

	void dfs(int i, int j, int curColor, ArrayList<Point>[][] g) {
		color[i][j] = curColor;
		for (Point to : g[i][j]) {
			if (color[to.y][to.x] == 0) {
				dfs(to.y, to.x, curColor, g);
			}
		}
	}

	boolean ret = false;

	void circleDFS(int i, int j, boolean[][] used) {
		if (ret) {
			return;
		}
		used[i][j] = true;
		if (used[toY[i][j]][toX[i][j]]) {
			getCircleSize(i, j, toY[i][j], toX[i][j]);
			ret = true;
			return;
		} else {
			circleDFS(toY[i][j], toX[i][j], used);
		}
	}

	int max;

	void getCircleSize(int i, int j, int toY, int toX) {
		max = Integer.MIN_VALUE;
		dfs1(toY, toX, 0, i, j, new boolean[1001][1001]);
		circlesInColor[color[i][j]] = max + 1;
	}

	void dfs1(int i, int j, int size, int toI, int toJ, boolean[][] used) {
		used[i][j] = true;
		if (i == toI && j == toJ) {
			if (max < size) {
				max = size;
			}
		}
		if (!used[toY[i][j]][toX[i][j]]) {
			dfs1(toY[i][j], toX[i][j], size + 1, toI, toJ, used);
		}
	}

	public void run() {
		try {
			br = new BufferedReader(new FileReader(fileName + ".in"));
			out = new PrintWriter(fileName + ".out");

			solve();

			out.close();
		} catch (IOException e) {
			e.printStackTrace();
			System.exit(1);
		}
	}

	BufferedReader br;
	StringTokenizer in;
	PrintWriter out;

	public String nextToken() throws IOException {
		while (in == null || !in.hasMoreTokens()) {
			in = new StringTokenizer(br.readLine());
		}
		return in.nextToken();
	}

	public int nextInt() throws IOException {
		return Integer.parseInt(nextToken());
	}

	public double nextDouble() throws IOException {
		return Double.parseDouble(nextToken());
	}

	public long nextLong() throws IOException {
		return Long.parseLong(nextToken());
	}

	public static void main(String[] args) throws IOException {
		Locale.setDefault(Locale.US);
		new SolveB_2().run();
	}

}