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<map>
#include<string>
#include<cstdio>

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

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

int main(){
	for(int h,w;scanf("%d%d",&h,&w),h;){
		char D[10][21];
		rep(i,h) scanf("%s",D[i]);

		map<string,int> f;
		rep(i,h) rep(j,w) rep(k,8) { // ツスツタツーツトツ暗環置ツづ陛サツ古シ
			int y=i,x=j;
			string s;
			do{
				s+=D[y][x];
				if(s.length()>=2) ++f[s];
				y=(y+dy[k]+h)%h;
				x=(x+dx[k]+w)%w;
			}while(y!=i||x!=j);
		}

		string s_ans;
		map<string,int>::iterator it;
		for(it=f.begin();it!=f.end();++it) if(it->second>=2) {
			if(s_ans.length()<it->first.length()
			|| s_ans.length()==it->first.length() && s_ans>it->first) s_ans=it->first;
		}
		puts(s_ans==""?"0":s_ans.c_str());
	}

	return 0;
}

C++: #include <bits/stdc++.h>
 
using namespace std;
 
int H,W;
bool visited[25][25];
char field[25][25];
map<string,int> mp;
const int dx[] = {-1,-1,-1,0,0,1,1,1};
const int dy[] = {-1,0,1,-1,1,-1,0,1};
 
void rec(int x,int y,int d,string s){
    if(visited[y][x]) return;
    visited[y][x] = true;
    int nx = (x + dx[d] + W) % W;
    int ny = (y + dy[d] + H) % H;
    mp[s+field[y][x]]++;
    rec(nx,ny,d,s+field[y][x]);
}
 
int main(){
    while(cin >> H >> W, H){
	mp.clear();
	for(int i = 0 ; i < H ; i++){
	    for(int j = 0 ; j < W ; j++){
		cin >> field[i][j];
	    }
	}
	for(int i = 0 ; i < H ; i++){
	    for(int j = 0 ; j < W ; j++){
		for(int k = 0 ; k < 8 ; k++){
		    memset(visited,false,sizeof(visited));
		    rec(j,i,k,"");
		}
	    }
	}
	int ans_size = -1;
	string ans;
	map<string,int>::iterator it;
	for(it = mp.begin() ; it != mp.end() ; ++it){
	    int size = it->first.size();
	    if(it->second < 2 || size < 2) continue;
	    if(ans_size < size){
		ans_size = size;
		ans = it->first;
	    }
	}
	if(ans_size == -1){
	    cout << 0 << endl;
	}else{
	    cout << ans << endl;
	}
    }
    return 0;
}

C++: #include <iostream>
#include <map>
#include <string>
#include <algorithm>
#define  MAX_H 10
using namespace std;

map<string, int> mp;
int dx[8] = {1, 0, -1, 0, 1, 1, -1, -1};
int dy[8] = {0, 1, 0, -1, 1, -1, 1, -1};

string s[MAX_H];
int h, w;

int mystrcmp(string a, string b) {
    if (a.size() > b.size()) return 1;
    if (a.size() < b.size()) return -1;

    for (int i = 0; i < a.size(); i++) {
        if (a[i] < b[i]) return 1;
        if (a[i] > b[i]) return -1;
    }
    return 0;
}

void dfs(int x, int y, int xnow, int ynow, int k, string str) {
    int xnext = (xnow + dx[k] + h) % h;
    int ynext = (ynow + dy[k] + w) % w;

    mp[str]++;

    if (x == xnext && y == ynext) return;
    
    string str2;
    str2.push_back(s[xnext][ynext]);
    dfs(x, y, xnext, ynext, k, str + str2);
}

int main() {
    while (true) {
        for (int i = 0; i < MAX_H; i++) {
            s[i].erase();
        }
        mp.clear();

        cin >> h >> w;
        if (h == 0 && w == 0) return 0;
        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++) {
                    string str;
                    str.push_back(s[i][j]);
                    dfs(i, j, i, j, k, str);
                }
            }
        }
        
        string ans;
        for (map<string, int>::const_iterator itr = mp.begin(); itr != mp.end(); ++itr) {
//            cout << itr->first << " " << itr->second << endl;
            if (itr == mp.begin()) {
                ans += itr->first;
                continue;
            }
            if (itr->second > 1 && mystrcmp(itr->first, ans) > 0) {
                ans.erase();
                ans += itr->first;
            }
        }

        if (ans.size() >= 2) cout << ans << endl;
        else cout << 0 << endl;
    }
}

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

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

int h,w;
char s[15][25];
string ans;

void dfs(int py,int px, int y, int x,int k,string cur,set<string> &dic){
    if(dic.count(cur)){
        if(cur.size() > ans.size()) ans = cur;
        if(cur.size() == ans.size()){
            if(cur < ans) ans = cur;
        }
    }
    else dic.insert(cur);

    if(px == x && py == y) return;

    int vx = (x+dx[k]+w) % w;
    int vy = (y+dy[k]+h) % h;

    dfs(py,px,vy,vx,k,cur+s[y][x],dic);
    return;
}

int main(){

    while(1){
        set<string> dic;
        cin>>h>>w;
        if(h == 0 && w == 0) break;

        for(int i=0; i<h; i++){
            for(int j=0; j<w; j++){
                cin>>s[i][j];
            }
        }

        ans = "";

        for(int i=0; i<h; i++){
            for(int j=0; j<w; j++){
                string cur = "";
                for(int k=0; k<8; k++){
                    int vx = (j+dx[k]+w) % w;
                    int vy = (i+dy[k]+h) % h;
                    dfs(i,j,vy,vx,k,cur+s[i][j],dic);
                }
            }
        }

        if(ans.size() <= 1) cout<<"0"<<endl;
        else cout<<ans<<endl;
    }

    return 0;
}

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

int main() {
    int N, M;
    while(cin >> N >> M, N || M) {
        vector<string> v(N);
        for(auto &i : v) cin >> i;

        string res = "";
        const int dx[] = {1, 1, 1, -1, -1, -1, 0, 0};
        const int dy[] = {-1, 0, 1, -1, 0, 1, -1, 1};
        set<string> s;
        for(int i = 0; i < N; i++) {
            for(int j = 0; j < M; j++) {
                for(int k = 0; k < 8; k++) {
                    int x = i;
                    int y = j;
                    int nx = (x + dx[k] + N) % N;
                    int ny = (y + dy[k] + M) % M;
                    string tmp = "";
                    tmp += v[i][j];
                    while(x != nx || y != ny) {
                        tmp += v[nx][ny];
                        nx = (nx + dx[k] + N) % N;
                        ny = (ny + dy[k] + M) % M;
                        if(res.size() <= tmp.size() && s.find(tmp) != s.end()) {
                            if(res.size() < tmp.size()) {
                                res = tmp;
                            } else if (res.size() == tmp.size()) {
                                res = min(res, tmp);
                            }
                        } else if (res.size() <= tmp.size()){
                            s.insert(tmp);
                        }
                    }
                }
            }
        }

        cout << (res == "" ? "0" : res) << endl;
    }

    return 0;
}