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 <string>
#include <vector>
#include <set>

using namespace std;

#define rep(i, n) for(int i=0; i<(n); ++i)
#define mp(a, b) make_pair(a, b)

template<typename T, typename Compare = greater<T> >
inline void chmax(T& t, T f, Compare comp){if(!comp(t, f))t = f;}

int h, w;

string solve(vector<string>& patterns){
    string res = "0";
    set<string> spells;
    rep(x, h)rep(y, w){
        for(int dx=-1; dx<=1; ++dx){
            for(int dy=-1; dy<=1; ++dy){
                string spell = "";  spell += patterns[x][y];
                for(int nx=(x+dx+h)%h, ny=(y+dy+w)%w; nx!=x || ny!=y; (nx+=(dx+h))%=h, (ny+=(dy+w))%=w){
                    spell += patterns[nx][ny];
                    if(!spells.insert(spell).second){
                        for(auto itr=spells.begin(); itr!=spells.end();){
                            if((*itr).size() < res.size())spells.erase(itr++); else itr++;
                        }
                        chmax(res, spell, [](string& s, string& t){return mp(t.size(), s) < mp(s.size(), t);});
                    }
                }
            }
        }
    }
    return res;
}

int main(){
    while(cin >> h >> w, h|w){
        vector<string> patterns(h);
        rep(i, h)cin >> patterns[i];
        cout << solve(patterns) << '\n';
    }
    return 0;
}

C++: #include <iostream>
#include <cstdio>
#include <map>

#define REP(i,n) for(int i=0; i<(int)(n); i++)
#define FOR(i,c) for(__typeof((c).begin()) i=(c).begin(); i!=(c).end(); i++)


using namespace std;

char d[20][30];

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

int main(){
  int h, w;

  while(scanf("%d%d", &h, &w), h + w){
    map<string, int> m;

    REP(i,h) scanf("%s", d[i]);

    REP(i,h) REP(j,w){
      REP(k,8){
        int x = j;
        int y = i;
        string tmp = "";

        do{
          tmp += d[y][x];
          x = (x + w + dx[k]) % w;
          y = (y + h + dy[k]) % h;
          m[tmp]++;
        }while(i != y || j != x);
      }
    }

    string ans = "";

    FOR(it, m) if(it->second > 1){
      const string &s = it->first;

      if(s.size() > ans.size()) ans = s;
      else if(s.size() == ans.size() && s < ans) ans = s;
    }

    if(ans.size() > 1) puts(ans.c_str());
    else puts("0");
  }

  return 0;
}

C++: #include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <string>
#include <set>
#include <map>
#include <list>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <cstdio>
#include <cmath>
#include <functional>

using namespace std;

#define PQ priority_queue
#define VT vector
#define MP make_pair
#define FOR(i, b, e) for(int i=b;i<e;i++)
#define CaseRead int _TT; scanf("%d", &_TT); for (int kase = 1; kase <= _TT; kase++)

typedef long long ll;

char ma[25][25];
int n, m;
vector<string> v;

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

void solve(int x, int y) {
//    printf("solve(%d, %d)\n", x, y);
    for (int i = 0; i < 8; i++) {
        string s = "";
        s += ma[x][y];
        int nx, ny;
        nx = (x + n + dx[i]) % n;
        ny = (y + m + dy[i]) % m;

        while (nx != x || ny != y) {
            s += ma[nx][ny];
            nx = (nx + n + dx[i]) % n;
            ny = (ny + m + dy[i]) % m;
        }
        v.push_back(s);
//        cout << s << endl;
    }
}



int main()
{
    while (1) {
        scanf("%d%d", &n, &m);
        v.clear();
        if (n == 0 && m == 0) break;
        for (int i = 0; i < n; i++) scanf("%s", ma[i]);
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++) solve(i, j);
        sort(v.begin(), v.end());
        int len = 0;
        string ans;

        for (int i = 1; i < v.size(); i++) {
//            cout << "compare " << v[i] << " and " << v[i-1] << endl;
            int len1 = 0;
            for (int j = 0; j < min(v[i].length(), v[i-1].length()) && v[i][j] == v[i-1][j]; j++) {
                len1++;
            }
            if (len1 > len) {
                len = len1;
                ans = v[i].substr(0, len1);
            }
        }
        if (ans.length() < 2) cout << 0 << endl;
        else cout << ans << endl;
            
    }

    return 0;
}

C++: #include<iostream>
#include<string>
#include<vector>
#include<cstdio>
#include<sstream>
#include<algorithm>
#include<cmath>
#include<map>
#include<functional>
#include<queue>
#include<stack>
#include<set>
using namespace std;
#define SZ(n)  (int)n.size()
#define dump(x) cerr<<#x<<" = "<<(x)<<endl;
#define debug(x)cerr << #x << " = " << (x) << " (L" << __LINE__ << ")" << " " << __FILE__ << endl;
#define MP make_pair
#define PB push_back
	


	int dx[]={1,1,0,-1,-1,-1,0,1},dy[]={0,1,1,1,0,-1,-1,-1};
	string _or(string a,string b){
		if(SZ(a)>SZ(b))return a;
		if(SZ(a)<SZ(b))return b;
		return min(a,b);
	}
	char ta[50][50];
	int main(){
	int w,h;
	while(cin>>h>>w,(h||w)){
	map<string,int>ans;
	for(int i=0;i<h;i++)for(int j=0;j<w;j++)cin>>ta[i][j];
	string tmp;

	for(int ni=0;ni<h;ni++){
		for(int nj=0;nj<w;nj++){
			for(int p=0;p<8;p++){
				tmp.clear();
				int i=ni,j=nj;
				tmp.push_back(ta[ni][nj]);
					while(true){
					i+=dy[p],j+=dx[p];
					if(i<0)i=h-1;
					if(j<0)j=w-1;
					if(i>h-1)i=0;
					if(j>w-1)j=0;
					if(i==ni&&j==nj)break;
					tmp.push_back(ta[i][j]);

					if(SZ(tmp)>=2){
					ans[tmp]++;
					}
					}
			}
		}
	}
	string tans="";
	for(map<string,int>::iterator it=ans.begin();it!=ans.end();it++){
	if((*it).second>=2){tans=_or(tans,(*it).first);}
	}
	if(SZ(tans)<2)cout<<"0"<<endl;
	else cout<<tans<<endl;
	for(int i=0;i<50;i++)for(int j=0;j<50;j++)ta[i][j]=' ';
	}
	return 0;
}