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<cstdlib>
#include<cstdio>
#include<stack>
#include<queue>
#include<map>
#include<algorithm>
#include<vector>
#include<cmath>
#include<cstring>
using namespace std;
char mape[22][22];
int m,n;
int dirx[]={ 1, 1, 1,-1,-1,-1, 0,  0};
int diry[]={ 1,-1, 0, 1, 0,-1, 1, -1};
vector<string> dic;
map<string, int> cou;
inline void cr(int x,int y,string s,int di){
	int i=x;
	int j=y;
	do{
		s+=mape[i][j];
		i+=dirx[di]+m;
		j+=diry[di]+n;
		i%=m;
		j%=n;
		cou[s]++;
		if(s.length()>1&&cou[s]==2)dic.push_back(s);
	}while(!(i==x&&j==y));
}
int aks(string a,string b){
	int aa=a.length();
	int bb=b.length();
	int l=min(aa,bb);
	if(aa==bb){
		for(int i=0;i<l;i++)
			if(a[i]!=b[i])return a[i]<b[i];
	}
	else return aa>bb;
}
int cmp(string a,string b){
	if(cou[a]==cou[b])return aks(a,b);
}
void pr(string s){
	cout<<s<<"\n";
}
void solve(){
	dic.clear();
	cou.clear();
	for(int i=0;i<m;i++)
		for(int j=0;j<n;j++)
			for(int ss=0;ss<8;ss++)
				cr(i,j,"",ss);
	sort(dic.begin(),dic.end(),cmp);
	/*cout<<"\n";
	for_each(dic.begin(),dic.end(),pr);
	cout<<"\n";*/
}
int main(){
	while(cin>>m>>n&&n+m>0){
		for(int i=0;i<m;i++)
			for(int j=0;j<n;j++)
				cin>>mape[i][j];
		solve();
		if(dic[0].length()>1)cout<<dic[0]<<"\n";
		else cout<<"0\n";
	}
}

C++: #include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>

using namespace std;

#define rep(i,j) REP((i), 0, (j))
#define REP(i,j,k) for(int i=(j);(i)<(k);++i)
#define BW(a,x,b) ((a)<=(x)&&(x)<=(b))
#define ALL(v) (v).begin(), (v).end()
#define LENGTHOF(x) (sizeof(x) / sizeof(*(x)))
#define AFILL(a, b) fill((int*)a, (int*)(a + LENGTHOF(a)), b)
#define SQ(x) ((x)*(x))
#define Mod(x, mod) (((x)+(mod)%(mod))
#define MP make_pair
#define PB push_back
#define Fi first
#define Se second
#define INF (1<<29)
#define EPS 1e-10
#define MOD 1000000007

typedef pair<int, int> pi;
typedef pair<string, pi> P;
typedef vector<int> vi;
typedef queue<int> qi;
typedef long long ll;

int H,W;
int dy[]={-1,-1,-1,0,1,1,1,0}, dx[]={-1,0,1,1,1,0,-1,-1};
char pat[16][32];
int vis[16][32];


string solve(){
  string res = "0";
  set<string>s;

  rep(i,H) rep(j,W){
    int sy=i,sx=j;
    rep(d,8){
      int ny=i,nx=j;
      string str="";
      str += pat[ny][nx];
      while(1){
	ny=(ny+dy[d]+H)%H, nx=(nx+dx[d]+W)%W;
	if(ny==sy&&nx==sx) break;
	str += pat[ny][nx];
	if(s.find(str) == s.end()){
	  s.insert(str);
	}else{
	  if(res.size() < str.size()) res = str;
	  else if(res.size() == str.size() && res > str) res = str;
	}
      }
    }
  }

  return res;
}

int main(){
  while(cin >> H >> W && H && W){
    rep(i,H) cin >> pat[i];
    cout << solve() << endl;
  }
  return 0;
}

C++: #include <vector>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <algorithm>
#include <utility>
#include <functional>
#include <sstream>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <climits>
#include <fstream>
using namespace std;
inline int toInt(string s) { int v; istringstream sin(s); sin >> v; return v;}
template<class T> inline string toStr(T x) { ostringstream sout; sout << x; return sout.str();}
typedef vector<int> vi;
typedef vector<vi>  vvi;
typedef vector<string> vs;
typedef pair<int, int> pii;
typedef long long ll;
#define ALL(a) (a).begin(),(a).end()
#define RALL(a) (a).rbegin(),(a).rend()
#define FOR(i,a,b) for(int i=(a);i<=(b);++i)
#define REP(i,n) FOR(i,0,(n)-1)
const double EPS = 1e-12;
const double PI = acos(-1.0);
const int INF = INT_MAX/10;

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

string best(string a, string b) {
	if(a.length() < b.length()) {
		return b;
	}
	if(a.length() == b.length() && b < a) {
		return b;
	}
	return a;
}

int main() {
	int h, w;
	while(cin >> h >> w, h) {
		vs field(h);
		REP(i, h) {
			cin >> field[i];
		}

		map<string, int> times;
		string ans;
		REP(i, h) {
			REP(j, w) {
				vvi visited(h, vi(w, -1));
				REP(d, 8) {
					string tmp;
					int y = i, x = j;
					while(visited[y][x] != d) {
						tmp += field[y][x];
						visited[y][x] = d;
						times[tmp]++;
						if(times[tmp] > 1) {
							ans = best(ans, tmp);
						}
						y = (y+dy[d]+h)%h;
						x = (x+dx[d]+w)%w;
					}
					
				}
			}
		}

		if(ans.length() < 2) {
			cout << 0 << endl;
		} else {
			cout << ans << endl;
		}
	}

	return 0;
}

C++: #include<iostream>
#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
const ll MOD = 1000000007;
const ll INF = (ll)1000000007 * 1000000007;
const double EPS = 1e-9;
typedef pair<int, int> P;
typedef unsigned int ui;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
int d1[8] = { 1,1,1,0,0,-1,-1,-1 };
int d2[8] = { 1,0,-1,1,-1,1,0,-1 };
int h, w;
int fh(int x) {
	return (x% h+h)%h;
}
int fw(int x) {
	return (x%w + w) % w;
}
int main() {
	while (cin >> h >> w, h) {
		char t[20][20];
		string s;
		rep(i, h) {
			cin >> s;
			rep(j, w) {
				t[i][j] = s[j];
			}
		}
		vector<string>v;
		rep(i, h) {
			rep(j, w) {
				rep(k, 8) {
				    string u;
				    u = t[i][j];
					int now = 1;
					while (!(fh(i + now*d1[k]) == i && fw(j + now*d2[k]) == j)) {
						u += t[fh(i + now * d1[k])][fw(j + now * d2[k])];
						v.push_back(u);
						now++;
					}
				}
			}
		}
		sort(v.begin(), v.end());
		int len = v.size();
		ui ma = 0; string out = "0";
		rep(i, len-1) {
			if (v[i] == v[i + 1] && ma < v[i].length()) {
				ma = v[i].length(); out = v[i];
			}
		}
		cout << out << endl;
	}
	return 0;
}