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<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<climits>
#include<iostream>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
#include<list>
#include<map>
#include<set>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
#define pb push_back
int dy[]={0, 0, 1, -1, 1, 1, -1, -1};
int dx[]={1, -1, 0, 0, 1, -1, 1, -1};
 
#define FOR(i,a,b) for (int i=(a);i<(b);i++)
#define RFOR(i,a,b) for (int i=(b)-1;i>=(a);i--)
#define REP(i,n) for (int i=0;i<(n);i++)
#define RREP(i,n) for (int i=(n)-1;i>=0;i--)

int gcd (int a,int b){
    if(a < b){
        int c = b;
        b = a;
        a = c;
    }

    if(a % b == 0)
        return b;
    return gcd(b,a % b);
}

int lcm(int a,int b){
    return a * b / gcd(a,b);
}

int main(){
    while(1){
        int h,w;
        scanf("%d%d",&h,&w);
        if(h == 0 && w == 0)
            break;

        char donuts[10][21];
        for(int i = 0;i < h;i++)
            scanf("%s",&donuts[i][0]);

        int maxi = 0;
        char s[1000] = "";
        for(int i = 0;i < h * w * 8;i++){
            for(int j = i + 1;j < h * w * 8;j++){
                int h1 = i / (w * 8),w1 = i % (w * 8) / 8,d1 = i % (w * 8) % 8;
                int h2 = j / (w * 8),w2 = j % (w * 8) / 8,d2 = j % (w * 8) % 8;
                int maxlen;
                if(d1 < 2)
                    maxlen = w;
                else if(d1 < 4)
                    maxlen = h;
                else
                    maxlen = lcm(w,h);
                if(d2 < 2){
                    if(maxlen > w)
                        maxlen = w;
                }
                else if(d2 < 4 && maxlen > h)
                    maxlen = h;

                int len = 0;
                char kari[1000];
                for(int k = 0;k < maxlen;k++){
                    int y1 = (h1 + dy[d1] * k + h) % h,x1 = (w1 + dx[d1] * k + w) % w;
                    int y2 = (h2 + dy[d2] * k + h) % h,x2 = (w2 + dx[d2] * k + w) % w;
                    if(donuts[y1][x1] == donuts[y2][x2]){
                        len++;
                        kari[k] = donuts[y1][x1];
                        kari[k + 1] = '\0';
                    }else
                        break;
                }
                if(maxi < len){
                    maxi = len;
                    strcpy(s,kari);
                }else if(maxi == len && strcmp(s,kari) > 0){
                    strcpy(s,kari);
                }
            }
        }
        if(strlen(s) > 1)
            printf("%s\n",s);
        else
            printf("0\n");
    }
    return 0;
}

C++: #include <iostream>
#include <vector>
#include <string>
#include <map>
using namespace std;
int dx[8] = {0,1,1,1,0,-1,-1,-1};
int dy[8] = {1,1,0,-1,-1,-1,0,1};
int main(){
  int h,w;
  while(cin>>h>>w,h){
    vector<string> s(h);
    for(int i = 0;i < h;i++){
      cin>>s[i];
    }
    map<string,int> mp;
    for(int i = 0;i < h;i++){
      for(int j = 0;j < w;j++){
	for(int d = 0;d < 8;d++){
	  int y = i, x = j;
	  string tmps = "";
	  tmps += s[i][j];
	  while(true){
	    int ny = (y+dy[d] + h)%h, nx = (x+dx[d] + w)%w;
	    if(ny == i && nx == j){
	      break;
	    }else{
	      tmps+=s[ny][nx];
	      mp[tmps]++;
	      x=nx,y=ny;
	    }
	  }
	}
      }
    }
    string ans;
    int maxsize = 0;
    for(auto itr = mp.begin();itr!=mp.end();itr++){
      if(itr->second >= 2 && itr->first.size() > maxsize){
	ans = itr->first;
	maxsize = itr->first.size();
      }
    }
    if(maxsize)cout << ans << endl;
    else cout << 0 << endl;
  }
  return 0;
}

C++: #include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
vector<string>vec;
char c[20][20]; int H, W; bool used[20][20];
int dx[8] = { 1,1,1,0,-1,-1,-1,0 };
int dy[8] = { -1,0,1,1,1,0,-1,-1 };
int main() {
	while (true) {
		cin >> H >> W; vec.clear(); if (H == 0)break;
		for (int i = 0; i < H; i++) {
			for (int j = 0; j < W; j++)cin >> c[i][j];
		}
		for (int i = 0; i < H; i++) {
			for (int j = 0; j < W; j++) {
				for (int k = 0; k < 8; k++) {
					for (int l = 0; l < 400; l++)used[l / 20][l % 20] = false;
					int cx = i, cy = j; string S; S += c[cx][cy]; used[cx][cy] = true;
					while (true) {
						cx += dx[k]; cy += dy[k];
						if (cx < 0)cx += H; if (cx >= H)cx -= H;
						if (cy < 0)cy += W; if (cy >= W)cy -= W;
						if (used[cx][cy] == true)break;
						used[cx][cy] = true; S += c[cx][cy]; vec.push_back(S);
					}
				}
			}
		}
		sort(vec.begin(), vec.end()); string T = "0";
		for (int i = 1; i < vec.size(); i++) {
			if (vec[i - 1] == vec[i]) {
				if (vec[i].size()>T.size())T = vec[i];
				else if (vec[i].size() == T.size())T = min(T, vec[i]);
			}
		}
		cout << T << endl;
	}
	return 0;
}

C++: #include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<set>
using namespace std;
typedef vector<int> vi;
set<string> cands;
int dy[]={-1,-1,-1,0,0,1,1,1};
int dx[]={-1,0,1,-1,1,-1,0,1};
int maxlength=0,h,w;
string ans="";
void check(int y,int x,string *board)
{
  for(int k=0;k<8;k++)
  {
    bool visited[h][w];
    memset(visited,false,sizeof(visited));
    int yy=y,xx=x;
    string str="";
    while(!visited[yy][xx])
    {
      str+=board[yy][xx];
      if(cands.find(str)!=cands.end())
      {
				int str_len=str.length();
				if(maxlength<str_len)
				{
	  			ans=str;
					maxlength=str_len;
				}
				else if(maxlength==str_len && str<ans)
				{
	  			ans=str;
					maxlength=str_len;
				}
      }
      else
      {
				cands.insert(str);
      }
      visited[yy][xx]=true;
      yy=(yy+dy[k]+h)%h;
      xx=(xx+dx[k]+w)%w;
    }
  }
}

int main()
{
  while(1) 
  {
    cin >> h >> w;
    if(h==0) break;
    string board[h];
    cands.clear();
    for(int i=0;i<h;i++)
    {
      cin >> board[i];
    }
    maxlength=0;
    ans="0";
    for(int i=0;i<h;i++)
    {
      for(int j=0;j<w;j++)
      {
				check(i,j,board);
      }
    }
    if(maxlength>=2)
    {
      cout << ans << endl;
     }
    else
    {
      cout << "0" << endl;
    }
  }
}