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 <cstring>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;

#define MAX_N 10
#define MAX_M 20
int n,m;
char table[MAX_N][MAX_M];
//向上
void DFS1(int i,int j,int dep,string& s)
{
	if(dep==n)
		return ;
	s += table[i][j];
	if(i==0)
		DFS1(n-1,j,dep+1,s);
	else
		DFS1(i-1,j,dep+1,s);
	return;
}
// 向右上
void DFS2(int i,int j,int dep,string& s)
{
	if(dep==n*m)
		return ;
	s += table[i][j];
	int nxt_i=i-1,nxt_j=j+1;
	if(nxt_i == -1)
		nxt_i = n-1;
	if(nxt_j == m)
		nxt_j = 0;
	DFS2(nxt_i,nxt_j,dep+1,s);
}
//向右
void DFS3(int i,int j,int dep,string& s)
{
	if(dep==m)
		return ;
	s += table[i][j];
	if(j==m-1)
		DFS3(i,0,dep+1,s);
	else
		DFS3(i,j+1,dep+1,s);
	return;
}
//向右下
void DFS4(int i,int j,int dep,string& s)
{
	if(dep==n*m)
		return ;
	s += table[i][j];
	int nxt_i=i+1,nxt_j=j+1;
	if(nxt_i == n)
		nxt_i = 0;
	if(nxt_j == m)
		nxt_j = 0;
	DFS4(nxt_i,nxt_j,dep+1,s);
}
void DFS5(int i,int j,int dep,string& s)
{
	if(dep==n)
		return ;
	s += table[i][j];
	if(i==n-1)
		DFS5(0,j,dep+1,s);
	else
		DFS5(i+1,j,dep+1,s);
	return;
}
//左下
void DFS6(int i,int j,int dep,string& s)
{
	if(dep==n*m)
		return ;
	s += table[i][j];
	int nxt_i=i+1,nxt_j=j-1;
	if(nxt_i == n)
		nxt_i = 0;
	if(nxt_j == -1)
		nxt_j = m-1;
	DFS6(nxt_i,nxt_j,dep+1,s);
}
//向左
void DFS7(int i,int j,int dep,string& s)
{
	if(dep==m)
		return ;
	s += table[i][j];
	if(j==0)
		DFS7(i,m-1,dep+1,s);
	else
		DFS7(i,j-1,dep+1,s);
	return;
}
//左上
void DFS8(int i,int j,int dep,string& s)
{
	if(dep==n*m)
		return ;
	s += table[i][j];
	int nxt_i=i-1,nxt_j=j-1;
	if(nxt_i == -1)
		nxt_i = n-1;
	if(nxt_j == -1)
		nxt_j = m-1;
	DFS8(nxt_i,nxt_j,dep+1,s);
}
int main()
{
	// freopen("in","r",stdin);
	
	while(scanf("%d%d ",&n,&m)&&(n+m)){
		memset(table,0,sizeof(table));
		for(int i=0;i<n;i++){
			scanf("%s",table[i]);
		}
		// for(int i=0;i<n;i++){
		// 	printf("%s\n",table[i]);
		// }
		vector<string> totalStr;
		for(int i=0;i<n;i++){
			for(int j=0;j<m;j++){
				string s="";
				DFS1(i,j,0,s);
				totalStr.push_back(s);
				s="";
				DFS2(i,j,0,s);
				totalStr.push_back(s);
				s="";
				DFS3(i,j,0,s);
				totalStr.push_back(s);
				s="";
				DFS4(i,j,0,s);
				totalStr.push_back(s);
				s="";
				DFS5(i,j,0,s);
				totalStr.push_back(s);
				s="";
				DFS6(i,j,0,s);
				totalStr.push_back(s);
				s="";
				DFS7(i,j,0,s);
				totalStr.push_back(s);
				s="";
				DFS8(i,j,0,s);
				totalStr.push_back(s);
			}
		}
		sort(totalStr.begin(),totalStr.end());
		int Max = 1;
		string ans ;
		for(int i=0;i<totalStr.size()-1;i++){
			string s1 = totalStr[i];
			string s2 = totalStr[i+1];
			bool isOK=true;
			for(int j=0;j<min(s1.length(),s2.length())&&isOK;j++){
				if(s1[j]!=s2[j]){
					if(j-1>Max){
						// cout << "s1:" << s1 << endl;
						// cout << "s2:" << s2 << endl;
						Max = j-1;
						ans = s1.substr(0,j);
					}
					isOK = false;
				}
			}
			if(isOK){
				if(s1.length() < s2.length() && s1.length() > Max){
					Max = s1.length();
					ans = s1;
				}
				else if(s1.length() >= s2.length() && s2.length()>Max){
					Max = s2.length();
					ans = s2;
				}
			}
		}
		if(Max==1)
			puts("0");
		else
			cout << ans << endl;
	}
	return 0;
}

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

constexpr int di8[] = {0, 1, 1, 1, 0, -1, -1, -1};
constexpr int dj8[] = {1, 1, 0, -1, -1, -1, 0, 1};

int solve(){
    int h, w;
    cin >> h >> w;
    if(h == 0) return 1;
    vector<string> s(h);
    for(int i=0;i<h;i++){
        cin >> s[i];
    }
    map<string,int> cnt;
    for(int k=0;k<8;k++){
        vector<vector<bool> > used(h, vector<bool>(w));
        for(int i=0;i<h;i++){
            for(int j=0;j<w;j++){
                if(used[i][j]) continue;
                int len = 0, ni = i, nj = j;
                string t;
                while(!used[ni][nj]){
                    t.push_back(s[ni][nj]);
                    used[ni][nj] = true;
                    ni = (ni+di8[k]+h)%h;
                    nj = (nj+dj8[k]+w)%w;
                }
                len = t.size();
                t += t;
                for(int l=0;l<len;l++){
                    for(int x=2;x<=len;x++){
                        cnt[t.substr(l,x)]++;
                    }
                }
            }
        }
    }
    string ans = "";
    for(auto p : cnt){
        string t = p.first;
        if(p.second >= 2){
            if(t.size() > ans.size()){
                ans = t;
            }else if(t.size() == ans.size()){
                ans = min(ans, t);
            }
        }
    }
    if(ans.empty()) ans = "0";
    cout << ans << endl;
    return 0;
}

int main(){
    while(solve()==0);
    return 0;
}

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

#define for_(i,a,b) for(int i=a;i<b;++i)
#define allof(a) a.begin(),a.end()
#define minit(a,b) memset(a,b,sizeof(a))

typedef long long ll;
typedef pair<int, int> pii;

struct Spell {
	int size; string s;
	Spell(int _size, string _s) : size(_size), s(_s) {}
};
bool operator > (const Spell& a, const Spell& b) {
	if (a.size > b.size) return true;
	if (a.size == b.size) return a.s < b.s;
	return false;
}

int h, w;
string pat[11];

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

void solve() {
	set<string> finds;
	set<Spell, greater<Spell> > setp;
	
	for_(i,0,h) for_(j,0,w) {
		for_(d,0,8) {
			int sx = (j + dx[d] + w) % w, sy = (i + dy[d] + h) % h;
			string s = "";
			s += pat[i][j];
			
			while (sx != j || sy != i) {
				s += pat[sy][sx];
				sx = (sx + dx[d] + w) % w;
				sy = (sy + dy[d] + h) % h;
			
				if (finds.find(s) != finds.end()) {
					setp.insert(Spell((int)s.size(), s));
				} else {
					finds.insert(s);
				}
			}
		}
	}
	
	if ((int)setp.size() == 0) {
		cout << 0 << endl;
		return;
	}
	set<Spell, greater<Spell> >::iterator it = setp.begin();
	cout << (*setp.begin()).s << endl;
}

int main() {
	while (cin >> h >> w, h) {
		for_(i,0,h) cin >> pat[i];
		solve();
	}
	return 0;
}