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++: //29
#include<iostream>
#include<string>
#include<set>

using namespace std;

int main(){
  for(int h,w;cin>>h>>w,h|w;){
    char g[10][21];
    for(int i=0;i<h;i++){
      cin>>g[i];
    }
    set<string> s;
    string t;
    for(int i=0;i<h;i++){
      for(int j=0;j<w;j++){
	for(int k=-1;k<=1;k++){
	  for(int l=-1;l<=1;l++){
	    string c;
	    int y=i,x=j;
	    c=g[y][x];
	    for(;;){
	      if(!s.insert(c).second&&(t.size()<c.size()||(t.size()==c.size()&&c<t))){
		t=c;
	      }
	      y=(y+k+h)%h;
	      x=(x+l+w)%w;
	      if(y==i&&x==j)break;
	      c+=g[y][x];
	    }
	  }
	}
      }
    }
    if(t.size()>=2){
      cout<<t<<endl;
    }else{
      cout<<0<<endl;
    }
  }
  return 0;
}

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;
			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];
		ans = "";

		set< string > strs;

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

		for(int i = 0; i < l[0]; i++) {
			for(int j = 0; j < l[1]; j++) {
				int pos[2];
				pos[0] = i;
				pos[1] = j;
				search( &strs, pos, donut );
			}
		}

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

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

C++: #include <iostream>
#include <string>
#include <set>
using namespace std;
string mp[11];
int w,h;
set <string> cnt;
string ans;
void check(int x,int y){
  string str;
  for(int i=-1;i<=1;i++)
    for(int j=-1;j<=1;j++){
      if(i==0 && j==0) continue;
      str = mp[y][x];
      int nx=(x+j+w)%w,ny=(y+i+h)%h;
      while(ny!=y || nx!=x){
	str+=mp[ny][nx],nx=(nx+j+w)%w,ny=(ny+i+h)%h;
      if(cnt.count(str)){
	if(str.size()>ans.size()) ans = str;
	else if(str.size()==ans.size()) ans = min(str,ans);
      }
      else cnt.insert(str);
      }
    }
}

int main(){
  while(1) {
    cin >> h >> w;
    cnt.clear();
  if(w == 0 && h == 0) break;
  for(int i=0;i<h;i++) cin >> mp[i];

  ans = "";
  for(int i=0;i<h;i++)
    for(int j=0;j<w;j++)check(j,i);
  if(ans.size()==0) ans = "0";
  cout << ans << endl;
  }
  return 0;
}

C++: #include <bits/stdc++.h>
#define rep(i, a, n) for(int i = a; i < n; i++)
#define repb(i, a, b) for(int i = a; i >= b; i--)
#define all(a) a.begin(), a.end()
#define o(a) cout << a << endl
#define int long long
#define first fi
#define second se
using namespace std;
typedef pair<int, int> P;

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

signed main(){
    int h, w;
    while(1){
        cin >> h >> w;
        if(h + w == 0) break;
        string s[11];
        rep(i, 0, h) cin >> s[i];
        string ans = "";
        set<string> st;
        rep(i, 0, h){
            rep(j, 0, w){
                rep(k, 0, 8){
                    int y = i;
                    int x = j;
                    string now = "";
                    now += s[i][j];                    
                    for(int l = 1;; l++){
                        y = (y + dy[k] + h) % h;
                        x = (x + dx[k] + w) % w;
                        if(y == i && x == j) break;
                        now += s[y][x];
                        if(!st.count(now)) st.insert(now);
                        else{
                            if(ans.size() == now.size()){
                                if(ans > now) ans = now;
                            }else if(ans.size() < now.size()){
                                ans = now;
                            }
                        }
                    }
                    // cout << i << " " << j << " " << k << " " << now << endl;
                }
            }
        }
        cout << ans << endl;
    }
}