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

int H, W;
char F[10][21];

string get(int y1, int x1, int y2, int x2, int d1, int d2) {
  static int dy[] = { 0, -1, -1, -1, 0, 1, 1, 1 };
  static int dx[] = { 1, 1, 0, -1, -1, -1, 0, 1 };
  string tmp;
  int sy1 = y1;
  int sx1 = x1;
  int sy2 = y2;
  int sx2 = x2;
  bool first = true;
  while(true) {
    if(F[y1][x1] != F[y2][x2]) break;
    if(!first && y1 == sy1 && x1 == sx1) break;
    if(!first && y2 == sy2 && x2 == sx2) break;
    first = false;
    tmp += F[y1][x1];
    y1 += dy[d1];
    x1 += dx[d1];
    y2 += dy[d2];
    x2 += dx[d2];
    // mod
    if(y1 < 0) y1 += H;
    if(x1 < 0) x1 += W;
    if(y2 < 0) y2 += H;
    if(x2 < 0) x2 += W;
    y1 %= H;
    x1 %= W;
    y2 %= H;
    x2 %= W;
  }
  return tmp;
}

int main() {
  while(true) {
    cin >> H >> W;
    if(H == 0 && W == 0) break;
    for(int i = 0; i < H; ++i) {
      cin >> F[i];
    }
    string ans;
    for(int y1 = 0; y1 < H; ++y1) {
      for(int x1 = 0; x1 < W; ++x1) {
        for(int y2 = 0; y2 < H; ++y2) {
          for(int x2 = 0; x2 < W; ++x2) {
            for(int d1 = 0; d1 < 8; ++d1) {
              for(int d2 = 0; d2 < 8; ++d2) {
                if(y1 == y2 && x1 == x2 && d1 == d2) continue;
                string tmp = get(y1, x1, y2, x2, d1, d2);
                if(tmp.size() > ans.size() || (tmp.size() == ans.size() && tmp < ans)) {
                  ans = tmp;
                }
              }
            }
          }
        }
      }
    }
    if(ans.size() < 2) cout << 0 << endl;
    else cout << ans << endl;
  }
}

C++: #include <bits/stdc++.h>

using namespace std;

#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define FOR(i, a, b) for(int i=(a);i<(b);i++)
#define REP(i, n) FOR(i, 0, n)
#define RFOR(i, a, b) for(int i=(a);i>=(b);i--)
#define RREP(i, n) RFOR(i, n, 0)
#define MFOR(i, m) for(auto i=(m).begin();i!=(m).end();i++)
#define ALL(a) (a).begin(), (a).end()
#define SZ(x) ((int)(x).size())

typedef long long int ll;
typedef pair<int, int> P;
typedef pair<ll, ll> Pll;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vll;
typedef vector<vll> vvll;

const double eps = 1e-10;
const int MOD = 1000000007;
const int INF = 1000000000;
const ll LINF = 1ll<<50;

template<typename T>
void printv(vector<T> const& s) {
  REP(i, SZ(s)) {
    cout << s[i];
    if(i == SZ(s)-1) {
      cout << endl;
    } else {
      cout << " ";
    }
  }
}

vi dx = {0, -1, -1, -1, 0, 1, 1, 1};
vi dy = {1, 1, 0, -1, -1, -1, 0, 1};

string solve(int h, int w, const vector<vector<char>> &donuts) {
  string res = "";
  map<string, bool> m;
  REP(i, h) {
    REP(j, w) {
      vector<string> s;
      REP(k, 8) {
        string tmp = "";
        int posi = i, posj = j;
        tmp += donuts[posi][posj];
        posi = (posi + dy[k] + h) % h;
        posj = (posj + dx[k] + w) % w;
        while(posi != i || posj != j) {
          s.push_back(tmp);
          // if(i == 4 && j == 5 && k == 5) cout << posi << ":" << posj << endl;
          tmp += donuts[posi][posj];
          posi = (posi + dy[k] + h) % h;
          posj = (posj + dx[k] + w) % w;
        }
        // if(i == 4 && j == 5 && k == 5) cout << tmp << endl;
        s.push_back(tmp);
      }
      //printv(s);
      REP(k, SZ(s)) {
        if(m[s[k]] && (res == "" || SZ(res) < SZ(s[k]) || (SZ(res) == SZ(s[k]) && s[k] < res))) {
          res = s[k];
        }
      }
      REP(k, SZ(s)) {
        m[s[k]] = true;
      }
    }
  }
  return res;
}

int main () {
  cin.tie(0);
  cout << fixed << setprecision(10);
  
  while(1) {
    int h, w; cin >> h >> w;
    if(h == 0 && w == 0) break;
    vector<vector<char>> donuts(h, vector<char>(w));
    REP(i, h) {
      REP(j, w) {
        cin >> donuts[i][j];
      }
    }
    string ans = solve(h, w, donuts);
    cout << ((SZ(ans) == 1) ? "0" : ans) << endl;
  }
}

C++: #include <bits/stdc++.h>
#define fi first
#define se second
using namespace std;
using P = pair<int,int>;

int h,w;
int d[2][8] = {{-1,-1,-1,0,0,1,1,1},{-1,0,1,-1,1,-1,0,1}};
vector<vector<P>> memo;
vector<string> s;

string solve();

int main() {
    while(1){
        cin >> h >> w;
        if(h + w == 0)break;
        s.resize(h);
        for(int i = 0;i < h;++i)
            cin >> s[i];
        cout << solve() << endl;
    }
    return 0;
}

string solve(){
    string ans;
    memo.assign(26,vector<P>(0,{0,0}));
    for(int i = 0;i < h;++i)
        for(int j = 0;j < w;++j)
            memo[s[i][j]-'A'].push_back({i,j});
    for(int alph = 0;alph < 26;++alph){
        int memosize = memo[alph].size();
        for(int j = 0;j < memosize;++j)
            for(int k = 0;k < memosize;++k){
                P memoj = memo[alph][j],memok = memo[alph][k];
                for(int dj = 0;dj < 8;++dj)
                    for(int dk = 0;dk < 8;++dk){
                        P nowj = memoj,nowk = memok;
                        string now;
                        if(j == k && dj == dk)continue;
                        while(s[nowj.fi][nowj.se] == s[nowk.fi][nowk.se]){
                            now += s[nowj.fi][nowj.se];
                            (nowj.fi += d[0][dj] + h) %= h;
                            (nowj.se += d[1][dj] + w) %= w;
                            (nowk.fi += d[0][dk] + h) %= h;
                            (nowk.se += d[1][dk] + w) %= w;
                            if(nowj == memoj && nowk == memok)break;
                        }
                        if(now.size() <= 1)continue;
                        if(now.size() > ans.size() || (now.size() == ans.size() && now < ans))
                            ans = now;
                    }
            }
    }
    return ans.size() == 0? "0":ans;
}