import java.io.*;
import java.util.*;
 
public class ascii_nn {
 
    static void solve() throws IOException {
        k = nextInt();
        w = nextInt();
        h = nextInt();
        c = new char[k][][];
        for (int it = 0; it < k; it++) {
            List<String> z = new ArrayList<>();
            while (true) {
                String line = br.readLine();
                if (line == null || line.equals(""))
                    break;
                z.add(line);
            }
            c[it] = new char[z.size()][];
            for (int j = 0; j < z.size(); j++) {
                c[it][j] = z.get(j).toCharArray();
            }
        }
        fx = new int[k];
        fy = new int[k];
        int top = 0;
        for (int it = 0; it < k; it++) {
            c[it] = norm(c[it]);
            char[][] d = c[it];
            all: for (int i = 0; i + h <= d.length; i++) {
                for (int j = 0; j + w <= d[i].length; j++) {
                    if (d[i][j] != '.' && d[i + h - 1][j] != '.'
                            && d[i + h - 1][j + w - 1] != '.'
                            && d[i][j + w - 1] != '.') {
                        fx[it] = i;
                        fy[it] = j;
                        break all;
                    }
                }
            }
            boolean has = false;
            for (int i = 0; !has && i < fx[it]; i++) {
                for (int j = 0; j < d[i].length; j++) {
                    if (d[i][j] != '.') {
                        has = true;
                        break;
                    }
                }
            }
            for (int j = 0; j < w; j++) {
                if (d[fx[it]][fy[it] + j] == '.') {
                    has = true;
                    break;
                }
            }
            if (!has) {
                top++;
            }
        }
        n = k / top;
        m = top;
        ans = new char[h * n][w * m];
        for (char[] e : ans)
            Arrays.fill(e, '.');
        was = new boolean[k];
        if (!go(0, 0)) {
            // return;
            throw new AssertionError();
        }
        out.println(w * m + " " + h * n);
        for (char[] e : ans) {
            out.println(e);
        }
    }
 
    static char[][] norm(char[][] c) {
        int i = 0;
        while (empty(c[i])) {
            ++i;
        }
        c = Arrays.copyOfRange(c, i, c.length);
        i = c.length - 1;
        while (empty(c[i])) {
            --i;
        }
        c = Arrays.copyOfRange(c, 0, i + 1);
        i = 0;
        while (emptyCol(c, i)) {
            ++i;
        }
        for (int j = 0; j < c.length; j++) {
            c[j] = Arrays.copyOfRange(c[j], i, c[j].length);
        }
        i = c[0].length - 1;
        while (emptyCol(c, i)) {
            --i;
        }
        for (int j = 0; j < c.length; j++) {
            c[j] = Arrays.copyOfRange(c[j], 0, i + 1);
        }
        return c;
    }
 
    static boolean emptyCol(char[][] c, int i) {
        for (int j = 0; j < c.length; j++) {
            if (c[j][i] != '.') {
                return false;
            }
        }
        return true;
    }
 
    static boolean empty(char[] c) {
        for (int i = 0; i < c.length; i++) {
            if (c[i] != '.') {
                return false;
            }
        }
        return true;
    }
 
    static boolean go(int x, int y) {
        if (y == m) {
            return true;
        }
        if (x == n) {
            return go(0, y + 1);
        }
        int cx = x * h;
        int cy = y * w;
        for (int it = 0; it < k; it++) {
            if (was[it]) {
                continue;
            }
            char[][] d = c[it];
            boolean canPut = true;
            all: for (int i = 0; i < d.length; i++) {
                for (int j = 0; j < d[i].length; j++) {
                    if (d[i][j] == '.') {
                        continue;
                    }
                    int di = i - fx[it] + cx;
                    int dj = j - fy[it] + cy;
                    if (di < 0 || dj < 0 || di >= ans.length
                            || dj >= ans[di].length || ans[di][dj] != '.') {
                        canPut = false;
                        break all;
                    }
                }
            }
            if (!canPut) {
                continue;
            }
            was[it] = true;
            for (int i = 0; i < d.length; i++) {
                for (int j = 0; j < d[i].length; j++) {
                    if (d[i][j] == '.') {
                        continue;
                    }
                    int di = i - fx[it] + cx;
                    int dj = j - fy[it] + cy;
                    ans[di][dj] = d[i][j];
                }
            }
            if (checkTop(x, y) && checkLeft(x, y) && checkDown(x - 1, y)
                    && checkRight(x, y - 1) && go(x + 1, y)) {
                return true;
            }
            for (int i = 0; i < d.length; i++) {
                for (int j = 0; j < d[i].length; j++) {
                    if (d[i][j] == '.') {
                        continue;
                    }
                    int di = i - fx[it] + cx;
                    int dj = j - fy[it] + cy;
                    ans[di][dj] = '.';
                }
            }
            was[it] = false;
        }
        return false;
    }
 
    static boolean check(int x, int y) {
        if (x < 0 || y < 0)
            return true;
        int cx = h * x;
        int cy = w * y;
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                if (ans[cx + i][cy + j] == '.') {
                    return false;
                }
            }
        }
        return true;
    }
 
    static boolean checkTop(int x, int y) {
        if (x < 0 || y < 0)
            return true;
        int cx = h * x;
        int cy = w * y;
        for (int j = 0; j < w; j++) {
            if (ans[cx][cy + j] == '.') {
                return false;
            }
        }
        return true;
    }
 
    static boolean checkDown(int x, int y) {
        if (x < 0 || y < 0)
            return true;
        int cx = h * x;
        int cy = w * y;
        for (int j = 0; j < w; j++) {
            if (ans[cx + h - 1][cy + j] == '.') {
                return false;
            }
        }
        return true;
    }
 
    static boolean checkLeft(int x, int y) {
        if (x < 0 || y < 0)
            return true;
        int cx = h * x;
        int cy = w * y;
        for (int i = 0; i < h; i++) {
            if (ans[cx + i][cy] == '.') {
                return false;
            }
        }
        return true;
    }
 
    static boolean checkRight(int x, int y) {
        if (x < 0 || y < 0)
            return true;
        int cx = h * x;
        int cy = w * y;
        for (int i = 0; i < h; i++) {
            if (ans[cx + i][cy + w - 1] == '.') {
                return false;
            }
        }
        return true;
    }
 
    static char[][] ans;
    static char[][][] c;
    static boolean[] was;
    static int[] fx, fy;
    static int n, m, k, w, h;
 
    public static void main(String[] args) throws Exception {
        File file = new File("ascii.in");
        InputStream input = System.in;
        PrintStream output = System.out;
        if (file.exists() && file.canRead()) {
            input = new FileInputStream(file);
            output = new PrintStream("ascii.out");
        }
        br = new BufferedReader(new InputStreamReader(input));
        out = new PrintWriter(output);
        solve();
        out.close();
    }
 
    static BufferedReader br;
    static StringTokenizer st;
    static PrintWriter out;
 
    static String nextToken() throws IOException {
        while (st == null || !st.hasMoreTokens()) {
            String line = br.readLine();
            if (line == null) {
                return null;
            }
            st = new StringTokenizer(line);
        }
        return st.nextToken();
    }
 
    static int nextInt() throws IOException {
        return Integer.parseInt(nextToken());
    }
 
    static long nextLong() throws IOException {
        return Long.parseLong(nextToken());
    }
 
    static double nextDouble() throws IOException {
        return Double.parseDouble(nextToken());
    }
}