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<cstring>
#include<iostream>
#include<string>
#include<map>
using namespace std;

int W,H,i,j,k,l,p,m[3]={0,1,-1},h,w,sh,sw;
char D[10][21];
string T,R;
map<string,int> S;
int main()
{
	for(;scanf("%d%d\n",&H,&W),H;)
	{
		S.clear();
		R="0";
		for(i=k=0,l=1;i<H;i++)gets(D[i]);
		for(sh=0;sh<H;sh++)
			for(sw=0;sw<W;sw++)
				for(i=0;i<3;i++)
					for(j=0;j<3;j++)
					{
						if(i==0&&j==0)continue;
						T.clear();
						for(h=sh,w=sw,p=0;!(p!=0&&h==sh&&w==sw);h=(h+m[i]+H)%H,w=(w+m[j]+W)%W,p++)
						{
							T+=D[h][w];
							if(S.find(T)!=S.end())
							{
								if(R.length()<T.length()||(R.length()==T.length()&&R>T))
									R=T;
							}
							else
								S.insert(map<string,int>::value_type(T,1));
						}
					}
		cout<<R<<endl;
	}
	return 0;
}

C++: #define _USE_MATH_DEFINES
#define INF 0x3f3f3f3f
#include <cstdio>
#include <iostream>
#include <sstream>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <limits>
#include <map>
#include <string>
#include <cstring>
#include <set>
#include <deque>
#include <bitset>
#include <list>
#include <cctype>
#include <utility>
 
using namespace std;
 
typedef long long ll;
typedef pair <int,int> P;
typedef pair <int,P > PP;
 
const static int tx[] = {0,1,1,1,0,-1,-1,-1};
const static int ty[] = {-1,-1,0,1,1,1,0,-1};

int main(){
  int H,W;
  while(~scanf("%d %d",&H,&W)){
    if(H==0 && W==0) break;

    char line[32];
    char stage[10][20];

    for(int y=0;y<H;y++){
      scanf("%s",line);
      for(int x=0;x<W;x++){
	stage[y][x] = line[x];
      }
    }

    string res = "";
    vector<string> spells;
    map<string,int> freq;
    
    for(int y=0;y<H;y++){
      for(int x=0;x<W;x++){
	int sx = x;
	int sy = y;

	for(int dir=0;dir<8;dir++){
	  string spell = "";
	  spell.push_back(stage[sy][sx]);
	  int dx = sx;
	  int dy = sy;
	  for(int i=0;i<1000;i++){
	    dx = tx[dir] + dx;
	    dy = ty[dir] + dy;
	    if(dx < 0) dx = W-1;
	    if(dx >= W) dx = 0;
	    if(dy < 0) dy = H-1;
	    if(dy >= H) dy = 0;

	    if(dy == sy && dx == sx) break;
	    spell.push_back(stage[dy][dx]);
	    freq[spell]++;
	    if(freq[spell] >= 2){
	      if(res.size() < spell.size()
		 || (res.size() == spell.size() && res < spell)){
		res = spell;
	      }
	    }
	  }
	  spells.push_back(spell);
	  // cout << spell << endl;
	}
      }
    }
    printf("%s\n",res != "" ? res.c_str() : "0");
  }
}

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 * 2000 ) % M][( startx + p*dx[k] + N * 2000 ) % N]);
						if(s.length() >= ans.length())
						{
							auto s2 = s;
							reverse(s2.begin() , s2.end());
							if(s2 <= s)
							{
								if(SS.find(s2) != SS.end() && ( ans.length() < s2.length() || ans > s2 ))
								{
									ans = s2;
								} else
								{
									SS.insert(s2);
								}
							}
						}
						p++;
					}
				}
			}
		}
		if(ans.length() <= 1)
		{
			cout << 0 << endl;
		} else
		{
			cout << ans << endl;
		}
	}
}

C++: #include <vector>
#include <iostream>
#include <utility>
#include <algorithm>
#include <string>
#include <deque>
#include <tuple>
#include <queue>
#include <functional>
#include <cmath>
#include <iomanip>
#include <map>
//cin.sync_with_stdio(false);
//streambuf
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;

constexpr int gcd(int a, int b){
	return b == 0 ? a : gcd(b, a%b);
}
int main() {
	int h, w;
	while (cin >> h >> w, h) {
		vector<string> map(h);
		for (auto &a : map)cin >> a;
		int dx[] = { 0,0,1,1,1,-1,-1,-1 };
		int dy[] = { 1,-1,0,-1,1,0,1,-1 };
		vector<tuple<string, int, int, int>> buf;
		for (int i = 0; i < h; i++) {
			for (int j = 0; j < w; j++) {
				for (int d = 0; d < 8; d++) {
					buf.push_back(make_tuple((string)"" + map[i][j], j, i, d));
				}
			}
		}
		int l = 0;
		for (; l < h*w / gcd(h, w); l++) {
			sort(buf.begin(), buf.end());
			vector<tuple<string, int, int, int>> buf2;
			for (int i = 1; i < buf.size(); i++) {
				if (get<0>(buf[i - 1]).size() < l)continue;
				if (get<0>(buf[i - 1]) == get<0>(buf[i]))buf2.push_back(buf[i - 1]);
				for (; i<buf.size()&&get<0>(buf[i - 1]) == get<0>(buf[i]); i++)buf2.push_back(buf[i]);
			}
			if (buf2.empty())break;
			buf = move(buf2);
			for (auto &a : buf) {
				string str;
				int x, y, d;
				tie(str, x, y, d) = a;
				int x1 = ((x + dx[d]*l) % w + w) % w;
				int y1 = ((y + dy[d]*l) % h + h) % h;
				if (x1 == x && y1 == y)continue;
				str += map[y1][x1];
				a = make_tuple(str, x, y, d);
			}
		}
		if (l < 3)cout << 0 << endl;
		else {
			string str = get<0>(buf[0]);
			cout << str.substr(0, l-1) << endl;
		}
	}
	return 0;
}