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 <cstdio>
#include <vector>
#include <string>
#include <cstring>
#include <set>
#include <map>
#include <queue>
#include <cmath>
#include <algorithm>
using namespace std;

#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)
#define ALL(c) (c).begin() , (c).end()

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

  int h,w;
  while(cin>>h>>w, h||w) {
    set<string> ap;
    char ba[h][w];
    REP(i, h) {
      REP(j, w) {
        cin >> ba[i][j];
      }
    }

    string ans = "";
    REP(i, h) {
      REP(j, w) {
        REP(k, 8) {
          string str = "";
          int y = i;
          int x = j;
          do {
            str += string(1,ba[y][x]);

            if(ap.find(str) != ap.end()) {
//                            cout<<str<<endl;
              if(ans == "" || ans.length() < str.length()
                 || (ans.length() == str.length() && str < ans))
                ans = str;
            }
            if(str.length() > 1) ap.insert(str);

            y += dy[k];
            x += dx[k];
            if (x<0) x = w-1;
            if (x>=w) x = 0;
            if (y<0) y = h-1;
            if (y>=h) y = 0;
            //cout << k << " " << j <<" " << i << " " << x << " " << y << endl;
            if (i==y && j==x) break;
          } while(1);


//                    cout << str << endl;
        }
      }
    }

    if(ans.length() == 0) ans = "0";
    cout<<ans<<endl;
  }
}

C++: #include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cassert>
//C++11
#if __cplusplus == 201103L
#include <tuple>
#endif

using namespace std;

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

template<class T> void debug(T begin, T end){ for(T i = begin; i != end; ++i) cout<<*i<<" "; cout<<endl; }

typedef long long ll;
const int INF = 100000000;
const double EPS = 1e-8;
const int MOD = 1000000007;
typedef pair<int, string> P;
int H, W;
bool used[20][20];
void rec(int x, int y, int dx, int dy, string s, map<string, int>& count, vector<string>& grid){
  count[s] += 1;
  used[y][x] = true;
  int nx = (x + dx + W) % W;
  int ny = (y + dy + H) % H;
  if(used[ny][nx]) return;
  rec(nx, ny, dx, dy, s + grid[ny][nx], count, grid);
}

int main(){
  int dx[8] = {1,1,1,0,-1,-1,-1,0};
  int dy[8] = {-1,0,1,1,1,0,-1,-1};
  while(cin>>H>>W && H){
    vector<string> grid(H);
    REP(y, H) cin>>grid[y];
    map<string, int> count;
    REP(y, H)REP(x, W)REP(r, 8){
      memset(used, 0, sizeof(used));
      rec(x, y, dx[r], dy[r], string() + grid[y][x], count, grid);
    }
    vector<P> v;
    FORIT(it, count)if((it->first).size() >= 2 && it->second >= 2) v.push_back(P(-1*(it->first).size(), it->first));
    string ans;
    if(v.empty()) ans = "0";
    else ans = (*min_element(v.begin(), v.end())).second;
    cout<<ans<<endl;
  }
  return 0;
}

C++: #include <iostream>
#include <unordered_set>
#include <algorithm>
using namespace std;

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

int main(){
    while(1){
        int h,w;
        cin >> h >> w;
        if(h==0) break;
        
        char c[10][20];
        for(int i=0; i<h; i++){
            for(int j=0; j<w; j++){
                cin >> c[i][j];
            }
        }
        unordered_set<string> spell;
        string ans = "0";
        for(int i=0; i<h; i++){
            for(int j=0; j<w; j++){
                for(int d=0; d<8; d++){
                    string str(1,c[i][j]);
                    int y=(i+dy[d]+h)%h;
                    int x=(j+dx[d]+w)%w;
                    while(y!=i || x!=j){
                        str += c[y][x];
                        auto itr = spell.find(str);
                        if(itr != spell.end()){
                            if(str.length()>ans.length() ||
                               (str.length()==ans.length() && str<ans)){
                                ans = str;
                            }
                        }else{
                            spell.insert(str);
                        }
                        y = (y+dy[d]+h)%h;
                        x = (x+dx[d]+w)%w;
                    }
                }
            }
        }
        cout << ans << endl;
    }
    return 0;
}

C++: #include <iostream>
#include <string>

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(){
	int h, w;
	string mp[10];
	while(cin >> h >> w, h){
		for(int i=0;i<h;i++) cin >> mp[i];
		string res = "";
		for(int i=0;i<w*h;i++){
			if(res.size() == w*h) break;
			int x1 = i/w, y1 = i%w;
			for(int j=i+1;j<w*h;j++){
				if(res.size() == w*h) break;
				int x2 = j/w, y2 = j%w;
				if(mp[x1][y1]!=mp[x2][y2]) continue;
				for(int di=0;di<8;di++){
					for(int dj=0;dj<8;dj++){
						string cur;
						int nx1 = (x1+dx[di]+h)%h, ny1 = (y1+dy[di]+w)%w;
						int nx2 = (x2+dx[dj]+h)%h, ny2 = (y2+dy[dj]+w)%w;
						if(mp[nx1][ny1]!=mp[nx2][ny2]) continue;
						cur += mp[x1][y1];
						while((x1 != nx1 || y1 != ny1) && (x2 != nx2 || y2 != ny2) && mp[nx1][ny1] == mp[nx2][ny2]){
							cur += mp[nx1][ny1];
							nx1 = (nx1+dx[di]+h)%h, ny1 = (ny1+dy[di]+w)%w;
							nx2 = (nx2+dx[dj]+h)%h, ny2 = (ny2+dy[dj]+w)%w;
						}
						if(cur.size() > res.size()) res = cur;
						else if(cur.size() == res.size()) res = min(res, cur);
					}
				}
			}
		}
		cout << (res=="" ? "0" : res) << endl;
	}
}