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++: #include<cstdio>
#include<iostream>
#include<string>
#include<map>
using namespace std;
static const int MAX_H = 10;

int h, w;
string s[MAX_H];

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

int main(){
	for(;;){
		scanf("%d %d", &h, &w);
		if(h == 0 && w == 0) break;
		for(int i = 0; i < h; i++) cin >> s[i];
		map<string, int> mpa;
		for(int i = 0; i < h; i++){
			for(int j = 0; j < w; j++){
				int sy = i;
				int sx = j;
				for(int k = 0; k < 8; k++){
					int cy = i;
					int cx = j;
					string str;
					str += s[sy][sx];
					mpa[str]++;
					for(;;){
						cy += dy[k];
						cx += dx[k];
						cy = (cy + h) % h;
						cx = (cx + w) % w;
						if(cy == sy && cx == sx) break;
						str += s[cy][cx];
						mpa[str]++;
					}
				}
			}
		}
		string res = "0";
		for(map<string, int>::iterator itr = mpa.begin(); itr != mpa.end(); itr++){
			if(itr->second < 2 || itr->first.length() < 2) continue;
			if(itr->first.length() > res.length() || (itr->first.length() == res.length() && itr->first < res)) res = itr->first;
		}
		cout << res << endl;
	}
}

C++: #include <iostream>
#include <string>
#include <vector>
#include <set>

using namespace std;

#define rep(i, n) for(int i=0; i<(n); ++i)
#define mp(a, b) make_pair(a, b)

template<typename T, typename Compare = greater<T> >
inline void chmax(T& t, T f, Compare comp){if(!comp(t, f))t = f;}

int h, w;

string solve(vector<string>& patterns){
    string res = "0";
    set<string> spells;
    rep(x, h)rep(y, w){
        for(int dx=-1; dx<=1; ++dx){
            for(int dy=-1; dy<=1; ++dy){
                string spell = "";  spell += patterns[x][y];
                for(int nx=(x+dx+h)%h, ny=(y+dy+w)%w; nx!=x || ny!=y; (nx+=(dx+h))%=h, (ny+=(dy+w))%=w){
                    spell += patterns[nx][ny];
                    if(!spells.insert(spell).second){
                        chmax(res, spell, [](string& s, string& t){return mp(t.size(), s) < mp(s.size(), t);});
                    }
                }
            }
        }
    }
    return res;
}

int main(){
    while(cin >> h >> w, h|w){
        vector<string> patterns(h);
        rep(i, h)cin >> patterns[i];
        cout << solve(patterns) << '\n';
    }
    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 <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<string> 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 ox,oy;
string ans;
bool vis[M][M];
void dfs(int x,int y,int d,int dep){

	store[dep]=mz[y][x];
	int nex=(x+dx[d]+nx)%nx;
	int ney=(y+dy[d]+ny)%ny;
	store[dep+1]=0;
	string ss(store);
	if(sid.count(ss)&&ss.length()>=2){
		if(ss.length()>ans.length())ans=ss;
		else if(ss.length()==ans.length()&&ss<ans){
			ans=ss;
		}
	}
	sid.insert(ss);
	vis[x][y]=1;
	if(!vis[nex][ney])dfs(nex,ney,d,dep+1);
	vis[x][y]=0;

}
void solve(){
	Set(vis,0);
	for(int i=0;i<ny;i++){
		for(int j=0;j<nx;j++){
			for(int k=0;k<8;k++){
				vis[j][i]=1;
				dfs(j,i,k,0);
				vis[j][i]=0;
			}
		}
	}
	if(ans.size())
		puts(ans.c_str());
	else puts("0");
}
int main() {
	ios_base::sync_with_stdio(0);
	while(~scanf("%d%d",&ny,&nx)&&ny&&nx){
		sid.clear();
		ans="";
		for(int i=0;i<ny;i++)scanf("%s",mz[i]);
		solve();

	}

















}

C++: #include <iostream>
#include <fstream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <algorithm>
using namespace std;
 
#define REP(i,n) for(int i=0; i<n; ++i)
#define FOR(i,a,b) for(int i=a; i<=b; ++i)
#define FORR(i,a,b) for (int i=a; i>=b; --i)
#define pi M_PI
 
typedef long long ll;
typedef vector<int> VI;
typedef vector<ll> VL;
typedef vector<VI> VVI;
typedef pair<int,int> P;
typedef pair<ll,ll> PL;

int mod(int x, int y){
    return x % y + (x < 0 ? y : 0);
}

int main() {
    int w, h;
    int dx[] = {1,1,1,0,0,0,-1,-1,-1}, dy[] = {1,0,-1,1,0,-1,1,0,-1};
    while (cin >> h >> w && w){
        vector<string> s(h);
        REP(i,h) cin >> s[i];

        map<string, int> mp;
        string ans;
        REP(si,h) REP(sj,w) REP(k,9){
            string res;
            res += s[si][sj];
            for (int i=mod(si+dx[k],h), j=mod(sj+dy[k],w); i!=si || j!=sj; i=mod(i+dx[k],h), j=mod(j+dy[k],w)){
                res += s[i][j];
                if (mp[res]){
                    if (res.length() > ans.length() || (res.length() == ans.length() && res < ans))
                        ans = res;
                }
                mp[res] = 1;
            }
        }
        if (ans.length() <= 1) cout << 0 << endl;
        else cout << ans << endl;
    }

    return 0;
}