#include <stdio.h>
#include <string.h>
#define HASHTABLE_SIZE 40000
#define SPELL_LENGTH 191
#define NULL_INDEX -1

/* グループ */
typedef struct {
	char value[SPELL_LENGTH + 1];
	int length;
	int number;
} Item;

Item hashtable[HASHTABLE_SIZE]; /* 配列から取り出せる全ての文字列 */
int bottomlength;

/* 文字列のハッシュ値を求める */
int hash(const char* s) {
	int i, h = 0, a = 3141, b = 2718;
	for (i = 0; s[i] != '\0'; i++, a = a * b % (HASHTABLE_SIZE - 1)) h = (a * h + s[i]) % HASHTABLE_SIZE;
	return h;
}

/* ハッシュ表を初期化する */
void init() {
	int i;
	bottomlength = 2;
	for (i = 0; i < HASHTABLE_SIZE; i++) {
		hashtable[i].length = 0;
		hashtable[i].number = 0;
	}
}

/* 指定された呪文の番号を返す */
int searchH(const char* s, int h) {
	int i;
	for (i = hash(s); hashtable[i].number != 0; i++) {
		if (strcmp(s, hashtable[i].value) == 0) return i;
	}
	return NULL_INDEX;
}
int search(const char* s) {
	return searchH(s, hash(s));
}

/* 指定された呪文を配列に追加し呪文に割り当てられた番号を返す */
int add(const char* s) {
	int h = hash(s);
	int i = searchH(s, h);
	if (i == NULL_INDEX) {
		for (i = h; hashtable[i].length >= bottomlength; i++); /* 挿入可能な場所を探す */
		/* 新しい呪文を追加する */
		hashtable[i].number = 0;
		hashtable[i].length = strlen(s);
		strncpy(hashtable[i].value, s, hashtable[i].length + 1);
	}
	hashtable[i].number++; /* 同じ呪文の追加回数を数える */
	return i;
}

int VECTOR[8][2] = {{0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1}, {-1, 0}, {-1, 1}};

int main(void) {
	int h, w; /* 文字配列の大きさ */
	char data[10][20];
	int i, j, k;

	/* データセット毎の処理 */
	while (scanf("%d%d\n", &h, &w) == 2 && h >= 3 && h <= 10 && w >= 3 && w <= 20) {
		/* 文字配列を読み込む */
		for (i = 0; i < h; i++) for (j = 0; j < w; j++) {
			scanf("%c\n", &data[i][j]);
		}

		init(); /* 初期化 */

		/* 配列から取り出せる全ての文字列を探索する */
		int answer = NULL_INDEX;
		for (i = 0; i < h; i++) for (j = 0; j < w; j++) /* 始点 */ for (k = 0; k < 8; k++) /* 方向 */ {
			int used[10*20] = {}; /* 配列中のある文字を使ったか */
			int y = i, x = j; /* 現在の参照位置 */
			char s[SPELL_LENGTH] = {}; /* 取り出した文字列 */
			int sl; /* 長さ */
			for (sl = 1; used[w*y+x] == 0; sl++, y = (h + y + VECTOR[k][0]) % h, x = (w + x + VECTOR[k][1]) % w) {
				used[w*y+x] = 1;
				s[sl-1] = data[y][x]; /* 1文字加える */
				/* 文字列が呪文か判定する */
				/* if (sl > 1 || (answer != NULL_INDEX && sl >= hashtable[answer].length)) { */
				if (sl >= bottomlength) {
					int index = add(s);
					/* 同じ文字列が2回以上出現しているときこの文字列を呪文の候補とする */
					if (hashtable[index].number >= 2) {
						if (answer == NULL_INDEX) {
							answer = index; /* 初めて見つけた呪文候補 */
						} else {
							/* 最も長く辞書順で若い文字列を呪文とする */
							if (hashtable[index].length > hashtable[answer].length || (hashtable[index].length == hashtable[answer].length && strcmp(hashtable[index].value, hashtable[answer].value) < 0)) {
								answer = index;
							}
						}
						bottomlength = sl;
					}
				}
			}
		}

		/* 出力 */
		if (answer == NULL_INDEX) printf("0\n");
		else printf("%s\n", hashtable[answer].value);
	}

	return 0;
}