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 <algorithm>
#include <iostream>
#include <vector>
#include <math.h>
#include <set>
#include <map>
#include <string>
#include <stack>
#include <queue>
#include <iomanip>
#include <numeric>
#include <tuple>
#include <bitset>
#include <complex>
#include <unistd.h>
#include <cassert>
#include <cctype>
#include <random>
#define _USE_MATH_DEFINES
#define _GLIBCXX_DEBUG
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> plglg;
typedef tuple<int, int, int> tiii;
typedef tuple<ll, ll, ll> tlglglg;
typedef complex<double> xy_t;
int dx[8] = {1, 1, 0, -1, -1, -1, 0, 1};
int dy[8] = {0, -1, -1, -1, 0, 1, 1, 1};
double pi = 3.141592653589793;
ll mod = 1000000007;
int intmax = 2147483647;
int intmin = -2147483648;
ll llmax = 9223372036854775807;
ll llmin = -9223372036854775807;
int iinf = intmax / 8;
ll inf = llmax / 8;
double eps = 1e-11;

string s[30];
string str[2000];
int n;
bool bo[30][30];

int main() {
    while (1) {
        int h, w;
        cin >> h >> w;
        if (h == 0) {
            break;
        }
        for (int i = 0; i < h; i++) {
            cin >> s[i];
        }
        int num = 0;
        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 < h; l++) {
                        fill(bo[l], bo[l] + w, false);
                    }
                    string ss = "";
                    int x = i;
                    int y = j;
                    while (!bo[x][y]) {
                        ss.push_back(s[x][y]);
                        bo[x][y] = true;
                        x = (x + h + dx[k]) % h;
                        y = (y + w + dy[k]) % w;
                    }
                    str[num] = ss;
                    num++;
                }
            }
        }
        n = h * w * 8;
        // for (int i = 0; i < n; i++) {
        //     cout << str[i] << endl;
        // }
        string ans = "";
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                string sa = str[i];
                string sb = str[j];
                int lena = sa.size();
                int lenb = sb.size();
                int numb = -1;
                int len = min(lena, lenb);
                for (int k = 0; k < len; k++) {
                    if (sa[k] != sb[k]) {
                        numb = k;
                        break;
                    }
                }
                if (numb == -1) {
                    numb = len;
                }
                int anslen = ans.size();
                if (numb > anslen) {
                    ans = sa.substr(0, numb);
                } else if (numb == anslen) {
                    if (sa.substr(0, numb) < ans) {
                        ans = sa.substr(0, numb);
                    }
                }
            }
        }
        int anslenb = ans.size();
        if (anslenb >= 2) {
            cout << ans << endl;
        } else {
            cout << 0 << endl;
        }
    }
}

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

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

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

map<string, int> mp;
vector<string> input;
int H, W;

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

void f(int x, int y, set<pii>& st, string& s, const int dir) {
  //  cout << x << " " << y << " " << dir <<" " << s << endl;
  //  cout <<mp.size() << endl;
  //  cout <<s.size() << " " << st.size() << " " << mp.size() << endl;
  s += input[y][x];
  mp[s]++;
  pii p;
  p = make_pair(y, x);
  st.insert(p);
  (x += dx[dir] + W) %= W;
  (y += dy[dir] + H) %= H;
  assert(x >= 0 && x < W);
  assert(y >= 0 && y < H);
  p = make_pair(y, x);
  if(st.count(p)) return;
  f(x, y, st, s, dir);
}

int main() {
  while(cin >> H >> W) {
    if(H == 0 && W == 0) break;
    mp.clear();
    input.resize(H);
    rep(i, H) cin >> input[i];
    rep(i, H) rep(j, W) rep(k, 8) {
      set<pii> st;
      string s;
      f(j, i, st, s, k);
    }
    string s;
    for(map<string, int>::iterator it = mp.begin(); it != mp.end(); ++it) {
      if(it->second == 1) continue;
      if(s.size() < it->first.size()) s = it->first;
      else {
	if(s.size() == it->first.size() && s > it->first) s = it->first;
      }
    }
    if(s.size() == 0) cout << 0 << endl;
    else cout << s << endl;
  }
  return 0;
}