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>

using namespace std;

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

int main()
{
	long long int M , N;
	while(cin >> M >> N , M || N)
	{
		vector<vector<char>>D(M , vector<char>(N));
		set<string>SS;
		string ans;
		for(size_t i = 0; i < M; i++)
		{
			for(size_t j = 0; j < N; j++)
			{
				cin >> D[i][j];
			}
		}
		for(long long int i = 0; i < M; i++)
		{
			for(long long int j = 0; j < N; j++)
			{
				long long int startx = j , starty = i;
				for(long long int k = 0; k < 8; k++)
				{
					long long int p = 1;
					string s;
					s.push_back(D[starty][startx]);
					while(!( ( startx + p*dx[k] + N * 2000 ) % N == startx && ( starty + p*dy[k] + M * 2000 ) % M == starty ))
					{
						s.push_back(D[( starty + p*dy[k] + M * 205 ) % M][( startx + p*dx[k] + N * 205 ) % N]);
						if(s.length() > ans.length())
						{
							if(SS.find(s) != SS.end())
							{
								ans = s;
							} else
							{
								SS.insert(s);
							}
						}
						p++;
					}
				}
			}
		}
		if(ans.length()<=1)
		{
			cout << 0 << endl;
		} else
		{
			cout << ans << endl;
		}
	}
}

C++: #include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <queue>
#define FI first
#define SE second
using namespace std;
const double EPS = 1e-10;
const int MAXN = 5005;
const int INF = 1111111111;
const double PI = acos(-1.0);
typedef long long LL;
int dcmp(double x)
{
    if(fabs(x)<EPS) return 0;
    return x<0?-1:1;
}
struct Point{
    double x,y;
    void input(){scanf("%lf%lf",&x,&y);}
}p[MAXN];

bool cmp(double a,double b)
{
    return dcmp(a-b)<0;
}
double ang[MAXN];
int main()
{
    //freopen("/home/qitaishui/code/in.txt","r",stdin);
    int n;
    int ca;
    LL ans,sub,tri;
    scanf("%d",&ca);
    while(ca--)
    {
        sub = 0;
        scanf("%d",&n);
        ans = (LL)n*(n-1)*(n-2)*(n-3)/24;
        tri = (n-1)*(n-2)*(n-3)/6;
        for(int i = 0; i < n;i++)
            p[i].input();
        int m;
        for(int i = 0;i < n; i++)
        {
            m = 0;
            for(int j = 0; j < n; j++)
            {
                if(i==j) continue;
                ang[m++] = atan2(p[j].y-p[i].y,p[j].x-p[i].x);
            }
            sort(ang,ang+m,cmp);
            for(int i = 0; i < m;i++)
                ang[i+m]=2*PI+ang[i];
            int l,r,s;
            s = l = 0;
            r = 1;
            tri = (n-1)*(n-2)*(n-3)/6;
            while(l < m)
            {
                while(dcmp(ang[l]+PI-ang[r])>=0)
                    r++,s++;
                if(s>=2)
                    tri-=(s-1)*s/2;
				s--;
                l++;
            }
            sub+=tri;
        }
        cout<<ans-sub<<endl;
    }
    return 0;
}

C++: #include<iostream>
#include<string>
#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;
    }
  }
}