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 <set>
using namespace std;

typedef unsigned long long ull;

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

int h,w;
string str[10];

void solve(){
  int y, x, ansn = 0;
  string ans = "0";
  set<string> s;
  for(int i=0;i<h;i++){
    for(int j=0;j<w;j++){
      for(int k=0;k<8;k++){
	string st;
	st += str[i][j];
	y = i;
	x = j;
	while(1){
	  y = (y + h + dy[k]) % h;
	  x = (x + w + dx[k]) % w;
	  if(y == i && j == x) break;
	  else st += str[y][x];
	  if(!s.empty() && s.find(st) != s.end()){
	    if(ansn < st.size() || ansn == st.size() && ans > st){
	      ans = st;
	      ansn = st.size();
	    }
	  } else s.insert(st);
	}

      }
    }
  }
  cout << ans << endl;
}

int main(){
  while(cin >> h >> w && (h|w)){
    for(int i=0;i<h;i++){
      cin >> str[i];
    }
    solve();
  }
}

C++: #include <bits/stdc++.h>
 
#define loop(n, i) for(int i=0;i<n;i++)
#define all(v) v.begin(),v.end()
#define HERE cout << "HERE: " << __LINE__ << endl;
#define INSP(v) cout << v << " at " << __LINE__ << endl;

using namespace std;
typedef long long ll;

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

int gcd(int a, int b)
{
    if (!a) return b;
    return gcd(b % a, a);
}

int main()
{
    string B[11];
    while (1) {
        vector<string> spells;
        int h, w; cin >> h >> w;
        if (!h) break;

        loop (h, i) cin >> B[i];

        int m = h * w / gcd(h, w);
        loop (h, i) loop (w, j) {
            int x = i, y = j;
            string left(w, ' ');
            left[0] = B[i][j];
            loop (w, k) {
                left[k] = B[x][y];
                y = (y + w - 1) % w;
            }
            spells.push_back(left);
            string right(w, ' ');
            x = i, y = j;
            loop (w, k) {
                right[k] = B[x][y];
                y = (y + 1) % w;
            }
            spells.push_back(right);
            string up(h, ' ');
            x = i, y = j;
            loop (h, k) {
                up[k] = B[x][y];
                x = (x + h - 1) % h;
            }
            spells.push_back(up);
            string down(h, ' ');
            x = i, y = j;
            loop (h, k) {
                down[k] = B[x][y];
                x = (x + 1) % h;
            }
            spells.push_back(down);

            vector<string> diags(4);
            loop (4, k) diags[k] = string(m, ' ');
            loop (4, p) {
                x = i, y = j;
                loop (m, k) {
                    diags[p][k] = B[x][y];
                    x = (x + dx[p] + h) % h;
                    y = (y + dy[p] + w) % w;
                }
            }
            spells.insert(spells.end(), diags.begin(), diags.end());
        }

        sort(all(spells));
        int l = spells.size();

        int m_cnt = 1;
        string ans;
        loop (l-1, i) {
            int j = 0;
            int len = min(spells[i].size(), spells[i+1].size());
            while (j < len && spells[i][j] == spells[i+1][j]) j++;
            if (j > m_cnt) {
                m_cnt = j;
                ans = spells[i].substr(0, j);
            }
        }
        if (m_cnt == 1) cout << 0 << endl;
        else cout << ans << endl;
    }
    return 0;
}

C++: 
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cfloat>
#include <cstring>
#include <map>
#include <utility>
#include <set>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
#include <sstream>
#include <complex>
#include <stack>
#include <queue>
#include <unordered_set>
#include <unordered_map>
using namespace std;

int dx[] = { 1,1,1,0,-1,-1,-1,0 };
int dy[] = { 1,0,-1,-1,-1,0,1,1 };
int main(void)
{
	for (;;)
	{
		int h, w; cin >> h >> w;
		if (!h)break;
		vector<string>donut;
		for (int i = 0; i < h; ++i)
		{
			string s; cin >> s;
			donut.push_back(s);
		}
		map<string, int>dic;
		for (int i = 0; i < h; ++i)
		{
			for (int j = 0; j < w; ++j)
			{
				for (int dir = 0; dir < 8; ++dir)
				{
					int ii = i, jj = j;
					set<pair<int, int>>st;
					string str;
					for (;;)
					{
						if (st.count({ ii,jj }))break;
						st.insert({ ii,jj });
						str.push_back(donut[ii][jj]);
						dic[str]++;
						ii += dx[dir]; jj += dy[dir];
						ii += h;
						jj += w;
						ii %= h;
						jj %= w;
					}
				}
			}
		}
		string ans = "0";
		for (auto page : dic)
		{
			if (page.second > 1)
			{
				const string& s = page.first;
				if (s.size() > ans.size())
				{
					ans = s;
				}
				else if (s.size() == ans.size())
				{
					if (s < ans)ans = s;
				}
			}
		}
		cout << ans << endl;
	}
	return 0;
}