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 <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)> dfs=[&](int y,int x){
        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]) continue;
            s.push_back(vs[ny][nx]);
            used[ny][nx]=true;
            dfs(ny,nx);
            s.pop_back();
            used[ny][nx]=false;
        }
    };
    rep(y,0,h) rep(x,0,w){
        s.push_back(vs[y][x]);
        used[y][x]=true;
        dfs(y,x);
        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;
}

C++: #include <cstdio>
#include <cstdlib>
#include <cstring>
#include <climits>
#include <cassert>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <algorithm>
#include <numeric>
#include <complex>
#include <stack>
#include <queue>
#include <list>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <bitset>
#include <functional>
#include <iterator>

using namespace std;

#define dump(n) cout<<"# "<<#n<<'='<<(n)<<endl
#define repi(i,a,b) for(int i=int(a);i<int(b);i++)
#define peri(i,a,b) for(int i=int(b);i-->int(a);)
#define rep(i,n) repi(i,0,n)
#define per(i,n) peri(i,0,n)
#define foreach(i,c) for(auto i=(c).begin();i!=(c).end();++i)
#define all(c) begin(c),end(c)
#define mp make_pair

typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef vector<string> vs;
typedef pair<int,int> pii;

const int INFTY=1<<29;
const double EPS=1e-9;

template<typename T1,typename T2>
ostream& operator<<(ostream& os,const pair<T1,T2>& p){
	return os<<'('<<p.first<<','<<p.second<<')';
}
template<typename T>
ostream& operator<<(ostream& os,const vector<T>& a){
	os<<'[';
	rep(i,a.size()) os<<(i?" ":"")<<a[i];
	return os<<']';
}

int main()
{
	for(int h,w;cin>>h>>w,h|w;){
		vs d(h);
		rep(i,h) cin>>d[i];
		map<string,int> cnt;
		int di[]={-1,-1,-1,0,0,1,1,1},dj[]={-1,0,1,-1,1,-1,0,1};
		rep(i0,h) rep(j0,w) rep(k,8){
			string s;
			vvi vis(h,vi(w));
			for(int i=i0,j=j0;!vis[i][j];i=(i+di[k]+h)%h,j=(j+dj[k]+w)%w){
				s+=d[i][j];
				vis[i][j]=1;
				cnt[s]++;
			}
		}
		string res;
		for(auto kv:cnt) if(kv.second>=2){
			string s=kv.first;
			if(s.size()>res.size() || s.size()==res.size() && s<res)
				res=s;
		}
		cout<<(res.size()>=2?res:"0")<<endl;
	}
}

C++: #include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <tuple>
#include <utility>
#include <vector>
using namespace std;

using ll = long long;

const int dh[8] = {1, 1, 0, -1, -1, -1, 0, 1}, dw[8] = {0, 1, 1, 1, 0, -1, -1, -1};

int H, W;
string m[10];

int main() {
    cin.tie(0); ios::sync_with_stdio(false);
    while (true) {
        cin >> H >> W;
        if (H+W == 0) break;
        for (int j = 0; j < H; ++j) {
            cin >> m[j];
        }

        string ans = "0";
        for (int a = 0; a < H*W; ++a) {
            int h1 = a / W, w1 = a % W;
            for (int b = a; b < H*W; ++b) {
                int h2 = b / W, w2 = b % W;
                if (m[h1][w1] != m[h2][w2]) continue;

                for (int d1 = 0; d1 < 8; ++d1) {
                    for (int d2 = ((h1==h2&&w1==w2)?(d1+1):0); d2 < 8; ++d2) {

                        string t = string(1, m[h1][w1]);
                        for (int j = 1; ; ++j) {
                            int nh1 = (h1 + dh[d1]*j + 100*H) % H;
                            int nw1 = (w1 + dw[d1]*j + 100*W) % W;

                            int nh2 = (h2 + dh[d2]*j + 100*H) % H;
                            int nw2 = (w2 + dw[d2]*j + 100*W) % W;

                            if ((nh1 == h1 && nw1 == w1) || (nh2 == h2 && nw2 == w2)) {
                                break;
                            }
                            if (m[nh1][nw1] != m[nh2][nw2]) {
                                break;
                            }

                            t.push_back(m[nh1][nw1]);
                        }
                        if (t.size() <= 1) continue;
                        if (t.size() >= 5) {
                        }

                        bool ok = false;
                        if (t.size() > ans.size()) {
                            ok = true;
                        } else if (t.size() == ans.size()) {
                            for (int j = 0; j < t.size(); ++j) {
                                if (t[j] < ans[j]) {
                                    ok = true;
                                    break;
                                } else if (t[j] > ans[j]) {
                                    break;
                                }
                            }
                        }
                        if (ok) {
                            ans = t.substr(0, t.size());
                        }
                    }
                }
            }
        }
        cout << ans << endl;
    }
        return 0;
    }