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 <bits/stdc++.h>
#define rep(i, a, n) for(int i = a; i < n; i++)
#define repb(i, a, b) for(int i = a; i >= b; i--)
#define all(a) a.begin(), a.end()
#define o(a) cout << a << endl
#define int long long
#define first fi
#define second se
using namespace std;
typedef pair<int, int> P;

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

signed main(){
    int h, w;
    while(1){
        cin >> h >> w;
        if(h + w == 0) break;
        string s[11];
        rep(i, 0, h) cin >> s[i];
        string ans = "";
        set<string> st;
        rep(i, 0, h){
            rep(j, 0, w){
                rep(k, 0, 8){
                    int y = i;
                    int x = j;
                    string now = "";
                    now += s[i][j];                    
                    for(int l = 1;; l++){
                        y = (y + dy[k] + h) % h;
                        x = (x + dx[k] + w) % w;
                        if(y == i && x == j) break;
                        now += s[y][x];
                        if(!st.count(now)) st.insert(now);
                        else{
                            if(ans.size() == now.size()){
                                if(ans > now) ans = now;
                            }else if(ans.size() < now.size()){
                                ans = now;
                            }
                        }
                    }
                    // cout << i << " " << j << " " << k << " " << now << endl;
                }
            }
        }
        if(ans == "") cout << "0" << endl;
        else cout << ans << endl;
    }
}

C++: #include <string>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int H, W; string s[11];
int main() {
	while (cin >> H >> W, H | W) {
		for (int i = 0; i < H; i++) cin >> s[i];
		vector<string> res;
		for (int i = 0; i < H; i++) {
			for (int j = 0; j < W; j++) {
				for (int dy = -1; dy <= 1; dy++) {
					for (int dx = -1; dx <= 1; dx++) {
						if (dx == 0 && dy == 0) continue;
						string now;
						int tx = (j + dx + W) % W, ty = (i + dy + H) % H;
						now += s[ty][tx];
						while (tx != j || ty != i) {
							tx = (tx + dx + W) % W, ty = (ty + dy + H) % H;
							now += s[ty][tx];
							res.push_back(now);
						}
					}
				}
			}
		}
		sort(res.begin(), res.end());
		string ret;
		int pre = 0;
		for (int i = 1; i < res.size(); i++) {
			if (i == res.size() || res[i - 1] != res[i]) {
				if (i - pre > 1) {
					if (ret.size() < res[pre].size() || (ret.size() == res[pre].size() && ret > res[pre])) {
						ret = res[pre];
					}
				}
				pre = i;
			}
		}
		if(ret.size() > 1) cout << ret << endl;
		else cout << 0 << endl;
	}
	return 0;
}

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 = "A";
  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 == "A" || 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;
  }
}