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++: /*
 * 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<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 ox,oy;
string ans;
Int isid;
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;
	isid=130*isid+store[dep];
	string ss(store);
	if(sid.count(isid)&&ss.length()>=2){
		if(ss.length()>ans.length())ans=ss;
		else if(ss.length()==ans.length()&&ss<ans){
			ans=ss;
		}
	}else sid.insert(isid);
	if(!vis[nex][ney]){
		vis[nex][ney]=1;
		dfs(nex,ney,d,dep+1);
		vis[nex][ney]=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++){
				isid=0;
				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 <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;

inline int add(int a, int b, int mod){
    int t = a + b;
    return t < mod? t < 0? mod + t: t: t - mod;
}

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=add(x, dx, h), ny=add(y, dy, w); nx!=x || ny!=y; nx=add(nx, dx, h), ny=add(ny, dy, 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++: #include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
vector<string>vec;
char c[20][20]; int H, W; bool used[20][20];
int dx[8] = { 1,1,1,0,-1,-1,-1,0 };
int dy[8] = { -1,0,1,1,1,0,-1,0 };
int main() {
	while (true) {
		cin >> H >> W; vec.clear(); if (H == 0)break;
		for (int i = 0; i < H; i++) {
			for (int j = 0; j < W; j++)cin >> c[i][j];
		}
		for (int i = 0; i < H; i++) {
			for (int j = 0; j < W; j++) {
				for (int k = 0; k < 8; k++) {
					for (int l = 0; l < 400; l++)used[l / 20][l % 20] = false;
					int cx = i, cy = j; string S; S += c[cx][cy]; used[cx][cy] = true;
					while (true) {
						cx += dx[k]; cy += dy[k];
						if (cx < 0)cx += H; if (cx >= H)cx -= H;
						if (cy < 0)cy += W; if (cy >= W)cy -= W;
						if (used[cx][cy] == true)break;
						used[cx][cy] = true; S += c[cx][cy]; vec.push_back(S);
					}
				}
			}
		}
		sort(vec.begin(), vec.end()); string T = "0";
		for (int i = 1; i < vec.size(); i++) {
			if (vec[i - 1] == vec[i]) {
				if (vec[i].size()>T.size())T = vec[i];
				else if (vec[i].size() == T.size())T = min(T, vec[i]);
			}
		}
		cout << T << endl;
	}
	return 0;
}

C++: #include <bits/stdc++.h>
using namespace std;

#define rep(i,x,y) for(int i=(x);i<(y);++i)
#define debug(x) #x << "=" << (x)

#ifdef DEBUG
#define _GLIBCXX_DEBUG
#define print(x) std::cerr << debug(x) << " (L:" << __LINE__ << ")" << std::endl
#else
#define print(x)
#endif

const int inf=1e9;
const int64_t inf64=1e18;
const double eps=1e-9;

template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec){
    os << "[";
    for (const auto &v : vec) {
    	os << v << ",";
    }
    os << "]";
    return os;
}

void solve(int h,int w){
    vector<string> vs(h);
    rep(i,0,h) cin >> vs[i];
    int dx[]={1,1,0,-1,-1,-1,0,1},dy[]={0,-1,-1,-1,0,1,1,1};
    set<string> st;
    vector<vector<bool>> used(h,vector<bool>(w));
    string s,ans;
    function<void(int,int,int)> dfs=[&](int y,int x,int i){
        if(st.find(s)!=st.end() and s.size()>=ans.size() and (s.size()>ans.size() or s<ans)) ans=s;
        st.insert(s);
        //rep(i,0,8){
        int ny=y+dy[i],nx=x+dx[i];
        if(ny==h) ny=0;
        if(ny<0) ny=h-1;
        if(nx==w) nx=0;
        if(nx<0) nx=w-1;
        if(used[ny][nx]) return;
        s.push_back(vs[ny][nx]);
        used[ny][nx]=true;
        dfs(ny,nx,i);
        s.pop_back();
        used[ny][nx]=false;
        //}
        return;
    };
    rep(y,0,h) rep(x,0,w) rep(i,0,8){
            s.push_back(vs[y][x]);
            used[y][x]=true;
            dfs(y,x,i);
            s.pop_back();
            used[y][x]=false;
    }

    if(ans.size()<2) cout << 0 << endl;
    else cout << ans << endl;
}
int main(){
    std::cin.tie(0);
    std::ios::sync_with_stdio(false);
    cout.setf(ios::fixed);
    cout.precision(10);
    for(;;){
        int h,w;
        cin >> h >> w;
        if(!h and !w) break;
        solve(h,w);
    }
    return 0;
}