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 <algorithm>
#include <map>
using namespace std;

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

bool comp(const string& a, const string& b)
{
	if(a.size() != b.size()) return a.size() > b.size();
	return a < b;
}

int main()
{
	int W, H;
	while(cin >> H >> W, (W||H)) {
		string field[10];
		for(int i=0; i<H; i++)
			cin >> field[i];

		string res;
		map<string, int> spells;
		for(int i=0; i<W; i++)
		for(int j=0; j<H; j++)
		for(int k=0; k<8; k++)
		{
			string s;
			int x = i, y = j;
			bool visit[10][20] = {0};
			while(1)
			{
				if(visit[y][x]) break;
				visit[y][x] = true;
				
				s += field[y][x];

				y = (y+dy[k]+H)%H;
				x = (x+dx[k]+W)%W;
				
				spells[s]++;
				if(spells[s] >=2 && comp(s,res)) res = s;
			}

		}

		if(res.size() <= 1) res = "0";
		cout << res << endl;
	}
}

C++: #include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
using namespace std;

int h,w;
string fie[11];
int dx[8]={1,0,-1,0,1,1,-1,-1};
int dy[8]={0,1,0,-1,1,-1,1,-1};
map<string,int> cnt;
bool used[11][21];
vector<string> index;

void dfs(int y,int x,int k,string str){
	if(used[y][x])return;
	used[y][x]=true;
	str+=fie[y][x];
	cnt[str]++;
	index.push_back(str);
	dfs((y+dy[k]+h)%h,(x+dx[k]+w)%w,k,str);
}

int main(void){
	while(1){
		scanf("%d %d",&h,&w);
		if(h+w==0)break;
		cnt.clear();
		index.clear();
		for(int i=0;i<h;i++){
			cin >> fie[i];
		}
		for(int i=0;i<h;i++){
			for(int j=0;j<w;j++){
				for(int k=0;k<8;k++){
					memset(used,false,sizeof(used));
					dfs(i,j,k,"");
				}
			}
		}
		sort(index.begin(),index.end());
		index.erase(unique(index.begin(),index.end()),index.end());
		string res="0";
		for(int i=0;i<index.size();i++){
			if(cnt[index[i]]>=2 && index[i].size()>=2){
				if(res.size()<index[i].size() || (res.size()==index[i].size() && index[i]<res)){
					res=index[i];
				}
			}
		}
		cout << res << endl;
	}
	return 0;
}

C++: #include<bits/stdc++.h>
#define range(i,a,b) for(int i = (a); i < (b); i++)
#define rep(i,b) for(int i = 0; i < (b); i++)
#define all(a) (a).begin(), (a).end()
#define debug(x) cout << "debug " << x << endl;
const int INF = 100000000;
using namespace std;

string m[1000];
string ans;
int h, w;
map<string, int> msi;

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

string big(string a, string b){
    if(a.size() > b.size()) return a;
    else if(a.size() < b.size()) return b;
    else{
        if(a < b) return a;
        else return b;
    }
}

void search(int y, int x){
    rep(i,8){
        string s;
        int j = 0;
        while(true){
            s += m[y + dy[i] * j][x + dx[i] * j];
            msi[s]++;
            if(msi[s] == 2){
                ans = big(ans, s);
            }
            j++;
            if(dy[i] * j % h == 0 && dx[i] * j % w == 0) break;
        }
    }
}

int main(){
    while(cin >> h >> w, h||w){
        rep(i,1000) m[i] = "";
        ans = "";
        msi.clear();
        rep(i,h){
            string s;
            cin >> s;
            rep(j,50) rep(k,50) m[i + j * h]+=s;
        }
        for(int i = h * 25; i < h * 26; i++){
            for(int j = w * 25; j < w * 26; j++){
                search(i,j);
            }
        }
        if(ans.size() < 2 ) cout << 0 << endl;
        else cout << ans << endl;
    }
}

C++: #include <iostream>
#include <string>
#include <stdio.h>
#include <set>

using namespace std;

#define dirmax 8

int l[2];
int dir[8][2] = { {0,1}, {1,0}, {-1,0}, {0,-1}, {1,1}, {-1,1}, {1,-1}, {-1,-1} };
string ans;

void search( set<string> *v, int pos[2] , char ch[10][20]){

	for(int i = 0; i < dirmax; i++) {
		string str;
		int cpos[] = { pos[0], pos[1] };

		str += ch[pos[0]][pos[1]];

		while( 1 ) {
			for(int j = 0; j < 2; j++) {
				cpos[j] += dir[i][j];
				if( cpos[j] < 0 ) cpos[j] = l[j] - 1;
				if( cpos[j] >= l[j] ) cpos[j] = 0;
			}
			if( cpos[0] == pos[0] && cpos[1] == pos[1] ) break;

			str += ch[cpos[0]][cpos[1]];
			
			if( v->find(str) != v->end() ) {
 				if( ( str.length() > ans.length() ) || ( str.length() == ans.length() && str < ans ) ) {
					ans = str;
				}
			} else 
				v->insert(str);
		}
	}
}

int main(void){
	while(1){
		cin >> l[0] >> l[1];
		if( l[0] == 0 && l[1] == 0 ) break;

		char donut[10][20];
		int pos[2];
		ans = "";

		set< string > strs;

		//入力を取得する
		for(int i = 0; i < l[0]; i++)
			cin >> donut[i];

		
		for(pos[0] = 0; pos[0] < l[0]; pos[0]++)
			for(pos[1] = 0; pos[1] < l[1]; pos[1]++)
				search( &strs, pos, donut );

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

	return 0;
}

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;
}