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<cstdlib>
#include<cstring>
#include<cmath>
#include<climits>
#include<iostream>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
#include<list>
#include<map>
#include<set>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
#define pb push_back
int dy[]={0, 0, 1, -1, 1, 1, -1, -1};
int dx[]={1, -1, 0, 0, 1, -1, 1, -1};
 
#define FOR(i,a,b) for (int i=(a);i<(b);i++)
#define RFOR(i,a,b) for (int i=(b)-1;i>=(a);i--)
#define REP(i,n) for (int i=0;i<(n);i++)
#define RREP(i,n) for (int i=(n)-1;i>=0;i--)

int gcd (int a,int b){
    if(a < b){
        int c = b;
        b = a;
        a = c;
    }

    if(a % b == 0)
        return b;
    return gcd(b,a % b);
}

int lcm(int a,int b){
    return a * b / gcd(a,b);
}

int main(){
    while(1){
        int h,w;
        scanf("%d%d",&h,&w);
        if(h == 0 && w == 0)
            break;

        char donuts[10][21];
        for(int i = 0;i < h;i++)
            scanf("%s",&donuts[i][0]);

        int maxi = 0;
        char s[1000] = "";
        for(int i = 0;i < h * w * 8;i++){
            for(int j = i + 1;j < h * w * 8;j++){
                int h1 = i / (w * 8),w1 = i % (w * 8) / 8,d1 = i % (w * 8) % 8;
                int h2 = j / (w * 8),w2 = j % (w * 8) / 8,d2 = j % (w * 8) % 8;
                int maxlen;
                if(d1 < 2)
                    maxlen = w;
                else if(d1 < 4)
                    maxlen = h;
                else
                    maxlen = lcm(w,h);
                if(d2 < 2){
                    if(maxlen > w)
                        maxlen = w;
                }
                else if(d2 < 4 && maxlen > h)
                    maxlen = h;

                int len = 0;
                char kari[1000];
                for(int k = 0;k < maxlen;k++){
                    int y1 = (h1 + dy[d1] * k + h * 1000) % h,x1 = (w1 + dx[d1] * k + w * 1000) % w;
                    int y2 = (h2 + dy[d2] * k + h * 1000) % h,x2 = (w2 + dx[d2] * k + w * 1000) % w;
                    if(donuts[y1][x1] == donuts[y2][x2]){
                        len++;
                        kari[k] = donuts[y1][x1];
                        kari[k + 1] = '\0';
                    }else
                        break;
                }
                if(maxi < len){
                    maxi = len;
                    strcpy(s,kari);
                }else if(maxi == len && strcmp(s,kari) > 0){
                    strcpy(s,kari);
                }
            }
        }
        if(strlen(s) > 1)
            printf("%s\n",s);
        else
            printf("0\n");
    }
    return 0;
}

C++: #include <cstdio>
#include <string>
#include <map>

using namespace std;

int h, w;
char str[32][32];

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

void generate(int sy, int sx, map<string, int> &rec)
{
	char tmp[2] = {0, 0};
	
	for (int i = 0; i < 8; i++){
		tmp[0] = str[sy][sx];
		string s = tmp;
		int ny = sy, nx = sx;
		while (1){
			ny = (ny + h + dy[i]) % h; nx = (nx + w + dx[i]) % w;
			if (ny == sy && nx == sx) break;
			tmp[0] = str[ny][nx];
			s += tmp;
			if (rec.count(s) > 0) rec[s] += 1;
			else rec[s] = 1;
		}
	}
}

int main()
{
	while (scanf("%d %d", &h, &w) && h){
		for (int i = 0; i < h; i++) scanf("%s", str[i]);
		map<string, int> occ;
		
		for (int i = 0; i < h; i++){
			for (int j = 0; j < w; j++){
				generate(i, j, occ);
			}
		}
		
		string ans = "";
		for (map<string, int>::iterator it = occ.begin(); it != occ.end(); it++){
			if (it->second > 1 && it->first.size() >= ans.size()){
				if (it->first.size() > ans.size()) ans = it->first;
				else if (it->first.size() == ans.size() && it->first < ans) ans = it->second;
			}
		}
		
		if (ans != "") printf("%s\n", ans.c_str());
		else printf("0\n");
	}
	return (0);
}

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)

int h, w;

string solve(vector<string>& patterns){
    auto comp = [](const string& s, const string& t){return mp(s.size(), t) < mp(t.size(), s);};
    set<string, decltype(comp)> spells(comp), magicSpells(comp);
    magicSpells.insert("0");
    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];
                    (spells.count(spell)? magicSpells: spells).insert(spell);
                }
            }
        }
    }
    return *(--magicSpells.end());
}

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 "bits/stdc++.h"
using namespace std;
vector<string> v;
int h,w;
string s[10];

string search(int a,int b,int d)
{
	int dirx[8]={1,1,0,-1,-1,-1,0,1};
	int diry[8]={0,-1,-1,-1,0,1,1,1};
	string ret;
	int i=a;
	int j=b;
	do{
		ret+=s[i][j];
		i+=dirx[d];
		j+=diry[d];
		if(i==-1)
			i=h-1;
		if(i==h)
			i=0;
		if(j==-1)
			j=w-1;
		if(j==w)
			j=0;
	}while(!(i==a && j==b));
	return ret;
}

bool comp(string a,string b)
{
	if(a.size()==b.size())
		return a<b;
	else
		return a.size()>b.size();
}

string itti(string a,string b)
{
	string ret;
	for(int i=0;i<min(a.size(),b.size());i++)
	{
		if(a[i]!=b[i])
			break;
		ret+=a[i];
	}
	return ret;
}

int main()
{
	while(1)
	{
		v.clear();
		cin>>h>>w;
		if(h==0)
			break;
		for(int i=0;i<h;i++)
			cin>>s[i];
		
		//すべての始点を調べる
		for(int i=0;i<h;i++)
		{
			for(int j=0;j<w;j++)
			{
				for(int k=0;k<8;k++)
					v.push_back(search(i,j,k));
			}
		}

		sort(v.begin(),v.end());
		string ans="0";
		for(int i=1;i<v.size();i++)
		{
			string tmp=itti(v[i],v[i-1]);
			if(comp(tmp,ans))
				ans=tmp;
		}
		cout<<ans<<endl;
	}
	return 0;
}