Go: package main

import "fmt"

var H, W int

type point struct {
	x, y int
}

func (p *point) add(q point) {
	p.x += q.x
	p.y += q.y
	if p.x < 0 {
		p.x += H
	}
	if p.y < 0 {
		p.y += W
	}
	p.x %= H
	p.y %= W
}

func isPalindrome(str string) bool {
	for i, j := 0, len(str)-1; i < j; i, j = i+1, j-1 {
		if str[i] != str[j] {
			return false
		}
	}
	return true
}

func magicSpel(arr []string) string {
	var ans string
	m := map[string]int{}
	for i := range arr {
		for j := range arr[i] {
			for _, d := range []point{{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}} {
				cur := point{x: i, y: j}
				str := string(arr[cur.x][cur.y])
				cur.add(d)
				for i != cur.x || j != cur.y {
					str += string(arr[cur.x][cur.y])
					cur.add(d)
					if isPalindrome(str) {
						m[str] += 2
					} else {
						m[str]++
					}
				}
			}
		}
	}
	for s, v := range m {
		if 1 < v {
			if len(ans) < len(s) {
				ans = s
			} else if len(ans) == len(s) && s < ans {
				ans = s
			}
		}
	}

	if len(ans) == 0 {
		return "0"
	}

	return ans
}

func main() {
	for {
		fmt.Scan(&H, &W)
		if H == 0 && W == 0 {
			break
		}

		var arr []string

		for i := 0; i < H; i++ {
			var s string
			fmt.Scan(&s)
			arr = append(arr, s)
		}

		fmt.Println(magicSpel(arr))
	}
}

// 2 3
// ABC
// DEF

C++: 
//http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1316

#include<iostream>
#include<map>
#include<vector>
#include<algorithm>
#include<cmath>
#include<climits>
#include<ctime>
#include<cstring>
#include<numeric>

#define ALL(v) (v).begin(),(v).end()
#define REP(i,p,n) for(int i=p;i<(int)(n);++i)
#define rep(i,n) REP(i,0,n)
#define dump(a) (cerr << #a << "=" << (a) << endl)
#define DUMP(list) cout << "{ "; for(auto nth : list){ cout << nth << " "; } cout << "}" << endl;

using namespace std;

int H,W;
vector< vector<char> > matrix;
map<string, int> spell_map;

int dx[8] = {1,1,0,-1,-1,-1,0,1};
int dy[8] = {0,1,1,1,0,-1,-1,-1};

string mystrcmp(string str1, string str2)
{
	if(str1.length() == str2.length()){
		return (str1 <= str2) ? str1 : str2;
	}else{
		return (str1.length() > str2.length()) ? str1 : str2;
	}
}

void dfs(int sx, int sy, int x, int y, int d, string spell)
{
	int nx = (x + dx[d] + W) % W;
	int ny = (y + dy[d] + H) % H;

	spell_map[spell]++;

	if(nx == sx && ny == sy){ 
		 return; 
	}else{
		dfs(sx,sy,nx,ny,d,spell+matrix[ny][nx]);
	}
}

int main()
{
	while(cin >> H >> W && H)
	{
		matrix.assign(H,vector<char>(W));
		spell_map.clear();
		
		rep(h,H){
			rep(w,W){
				cin >> matrix[h][w];
			}
		}

		rep(y,H){
			rep(x,W){
				rep(d,8){
					string str;
					str = str + matrix[y][x];
					dfs( x, y, x, y, d, str);
				}
			}
		}

		string ans;
		for(auto &it : spell_map){
			if(it.second >= 2){
				ans = mystrcmp( ans, it.first );
			}
		}

		cout << ((ans.length() >= 2) ? ans : "0") << endl;
	}
	return 0;
}

C++: /*
 * GCA : "Computer is artificial subject absolutely,Math is God"
 */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <climits>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <cctype>
#include <utility>
#include <ctime>
using namespace std;
#ifdef DEBUG
#define VAR(a,b) __typeof(b) a=(b)
#define debug(...) printf("DEBUG: "),printf(__VA_ARGS__)
#else
#define VAR(a,b) __typeof(b) a=(b)
#define debug(...)
#endif
typedef unsigned int uint;
typedef long long int Int;
typedef unsigned long long int UInt;
#define Set(a,s) memset(a,s,sizeof(a))
#define Pln() printf("\n")
#define For(i,x)for(int i=0;i<x;i++)
#define CON(x,y) x##y
#define M 25
#define PB push_back
#define oo INT_MAX
#define FOR(a,b) for(VAR(a,(b).begin());a!=(b).end();++a)
#define eps 1e-9
#define X first
#define Y second
inline bool xdy(double x,double y){return x>y+eps;}
inline bool xddy(double x,double y){return x>y-eps;}
inline bool xcy(double x,double y){return x<y-eps;}
inline bool xcdy(double x,double y){return x<y+eps;}
const Int mod=1000000007;
int nx,ny;
char mz[M][M];
set<Int> sid;
int dx[8]={0,1,1,1,0,-1,-1,-1};
int dy[8]={1,1,0,-1,-1,-1,0,1};
char store[M*M];
Int ist=0;
int ox,oy;
string ans;
//string has[M][M][9];
//bool vis[M][M][9];
void dfs(int x,int y,int d,int dep){

	store[dep]=mz[y][x];
	ist=ist*134+mz[y][x];
	int nex=(x+dx[d]+nx)%nx;
	int ney=(y+dy[d]+ny)%ny;
	store[dep+1]=0;
	string ss(store);
//		puts(store);
	if(sid.count(ist)){
		if(ss.length()>ans.length()){
			ans=ss;
		}else if(ss.length()==ans.length()&&ss<ans){
			ans=ss;
		}
	}
	sid.insert(ist);
	if(nex==ox&&ney==oy){
		return;
	}
	dfs(nex,ney,d,dep+1);

}
void solve(){
	for(int i=0;i<ny;i++){
		for(int j=0;j<nx;j++){
			for(int k=0;k<8;k++){
				ox=j;oy=i;
				ist=0;
				Set(store,0);
				dfs(j,i,k,0);
			}
		}
	}
//	for(int i=0;i<8;i++){
//		ox=1;oy=1;
//		dfs(1,1,i,0);
//	}
	if(ans.length()>=2)
		printf("%s\n",ans.c_str());
	else puts("0");
}
int main() {
	ios_base::sync_with_stdio(0);
	while(~scanf("%d%d",&ny,&nx)&&nx+ny){
		sid.clear();
		ans="";
//		Set(vis,0);
		for(int i=0;i<ny;i++)scanf("%s",mz[i]);
		solve();

	}

















}

C++: #include <bits/stdc++.h>

using namespace std;

#define INF 1001000100010001000
#define MOD 1000000007
#define EPS 1e-10
#define int long long
#define rep(i, N) for (int i = 0; i < N; i++)
#define Rep(i, N) for (int i = 1; i < N; i++)
#define For(i, a, b) for (int i = (a); i < (b); i++)
#define pb push_back
#define mp make_pair
#define i_i pair<int, int>
#define vi vector<int>
#define vvi vector<vi >
#define vb vector<bool>
#define vvb vector<vb >
#define vp vector< i_i >
#define all(a) (a).begin(), (a).end()
#define Int(x) int x; scanf("%lld", &x);

//int dxy[5] = {0, 1, 0, -1, 0};
int dx[8] = {1, 1, 1, 0, 0, -1, -1, -1};
int dy[8] = {1, 0, -1, 1, -1, 1, 0, -1};
// assign

string comp(string a, string b);

signed main()
{
    int n, m;
    while (cin >> n >> m, n) {
        vector<string> donut(n);
        rep(i, n) {
            cin >> donut[i];
        }
        set<string> can;
        string ans = "z";
        rep(i, n) {
            rep(j, m) {
                rep(k, 8) {
                    vvb used(n, vb(m, false));
                    string spell;
                    int x = i, y = j;
                    while (!used[x][y]) {
                        spell.pb(donut[x][y]);
                        used[x][y] = true;
                        if (can.find(spell) != can.end()) {
                            ans = comp(ans, spell);
                        } else {
                            can.insert(spell);
                        }
                        x = (x + dx[k] + n) % n; y = (y + dy[k] + m) % m;
                    }
                }
            }
        }
        cout << ((ans.length() > 1) ? ans : 0) << endl;
    }
    return 0;
}

string comp(string a, string b)
{
    if (a.length() < b.length()) {
        return b;
    } else if (a.length() > b.length()) {
        return a;
    } else {
        rep(i, a.length()) {
            if (a[i] < b[i]) {
                return a;
            } else if (a[i] > b[i]) {
                return b;
            }
        }
    }
    return a;
}