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;

#define fi first
#define se second
#define repl(i,a,b) for(int i=(int)(a);i<(int)(b);i++)
#define rep(i,n) repl(i,0,n)
#define each(itr,v) for(auto itr:v)
#define pb(s) push_back(s)
#define mp(a,b) make_pair(a,b)
#define all(x) (x).begin(),(x).end()
#define dbg(x) cout<<#x"="<<x<<endl
#define maxch(x,y) x=max(x,y)
#define minch(x,y) x=min(x,y)
#define uni(x) x.erase(unique(all(x)),x.end())
#define exist(x,y) (find(all(x),y)!=x.end())
#define bcnt(x) bitset<32>(x).count()

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> P;
typedef pair<P, int> PPI;
typedef pair<ll, ll> PL;
typedef pair<P, ll> PPL;

#define INF INT_MAX/3

#define MAX_N 1000

int h,w;
string s[11];

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

int main(){
	cin.sync_with_stdio(false);
	while(1){
		cin>>h>>w;
		if(h==0)break;
		rep(i,h)cin>>s[i];
		string res="";
		map<string,int> smap;
		rep(i,h)rep(j,w){
			rep(d,8){
				string ss;
				ss+=s[i][j];
				int ny=i+dy[d],nx=j+dx[d];
				if(ny>=h)ny=0;
				if(ny<0)ny=h-1;
				if(nx>=w)nx=0;
				if(nx<0)nx=w-1;
				while(ny!=i||nx!=j){
					ss+=s[ny][nx];
					smap[ss]++;
					if(smap[ss]==2){
						if(ss.length()>res.length()||(ss.length()==res.length()&&ss<res)){
							res=ss;
						}
					}
					ny+=dy[d],nx+=dx[d];
					if(ny>=h)ny=0;
					if(ny<0)ny=h-1;
					if(nx>=w)nx=0;
					if(nx<0)nx=w-1;
				}
			}
		}
		if(res=="")cout<<0<<endl;
		else cout<<res<<endl;
	}
	return 0;
}

C++: #include <bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef pair<int, int> pii;

pii d[8] = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}};

int main() {
  cin.tie(0);
  ios_base::sync_with_stdio(false);
  
  int h, w;
  while (cin >> h >> w, h) {
    vector<string> s(h);
    for (int i = 0; i < h; i++) {
      cin >> s[i];
    }

    map<string, int> cnt;
    for (int i = 0; i < h; i++) {
      for (int j = 0; j < w; j++) {
        for (int k = 0; k < 8; k++) {
          pii now = {i, j};
          string t = "";
          do {
            t += s[now.first][now.second];
            cnt[t]++;
            now.first += d[k].first, now.second += d[k].second;
            if (now.first < 0) now.first = h - 1;
            else if (now.first >= h) now.first = 0;
            if (now.second < 0) now.second = w - 1;
            else if (now.second >= w) now.second = 0;
          } while (now != pii(i, j));
        }
      }
    }

    int szMax = 1;
    string ans = "0";
    for (auto& i : cnt) {
      if (i.second == 1) continue;
      if (i.first.size() > szMax) {
        ans = i.first;
        szMax = ans.size();
      }
    }
    cout << ans << endl;
  }

  return 0;
}

C++: #include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <map>

#define REP(i,a,b) for(int i=int(a);i<int(b);i++)

using namespace std;

typedef long long int lli;

int main () {
    int h, w;
    while (cin >> h >> w, h + w) {
        vector<vector<char>> spell(h, vector<char>(w));
        REP (i, 0, h) REP (j, 0, w) cin >> spell[i][j];
        map<string, int> ml;
        REP (i, 0, h) REP (j, 0, w) {
            REP (dy, -1, 2) REP (dx, -1, 2) {
                if (dx == 0 && dy == 0) continue;
                vector<vector<bool>> isAccess(h, vector<bool>(w, false));
                int y = i, x = j;
                string temp = "";
                REP (_, 0, w * h) {
                    if (isAccess[y][x]) break;
                    isAccess[y][x] = true;
                    temp += spell[y][x];
                    ml[temp]++;

                    y = (y + dy + h) % h;
                    x = (x + dx + w) % w;
                }
            }
        }
        string ans = "";
        for (auto s : ml) {
            if (s.second <= 1 || s.first.size() <= 1) continue;
            if (ans.size() < s.first.size()) ans = s.first;
            else if (ans.size() == s.first.size()) ans = min(ans, s.first);
        }
        cout << (ans.size() == 0 ? "0" : ans) << endl;

    }
    return 0;
}

C++: #include <iostream>
#include <algorithm>
#include <string>
#include <set>

#define sz(x) int((x).size())
#define phb push_back
using namespace std;

const int kDir[8][2] = {{1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, {-1, -1}, {0, -1}, {1, -1}};

int H, W;
string P[10];

void read();
void solve();

int main() {
	while (cin >> H >> W, H + W)
		read(), solve();
	
	return 0;
}

void read() {
	for (int i = 0; i < H; ++i)
		cin >> P[i];
}

void solve() {
	static int visit[10][20], vst_cnt;
	string res;
	set< string > s;
	auto cmpf = [&] (const string &ra, const string &rb) -> string {
		if (sz(ra) != sz(rb))
			return sz(ra) > sz(rb) ? ra : rb;
		else
			return min(ra, rb);
	};
	
	for (int i = 0; i < H; ++i)
		for (int j = 0; j < W; ++j)
			for (int d = 0; d < 8; ++d) {
				string t;
				vector< string > v;
				
				int i_ = i, j_ = j;
				++vst_cnt;
				while (visit[i_][j_] != vst_cnt) {
					t.phb(P[i_][j_]), visit[i_][j_] = vst_cnt;
					if (sz(t) >= 2) {
						if (s.count(t) != 0)
							res = cmpf(res, t);
						v.phb(t);
					}
					i_ = (i_ + kDir[d][0] + H) % H, j_ = (j_ + kDir[d][1] + W) % W;
				}
				
				for (auto itr = v.begin(); itr != v.end(); ++itr)
					s.insert(*itr);
			}
	
	cout << (res != "" ? res : "0") << "\n";
}

C++: #include <bits/stdc++.h>

using namespace std;

int h, w;
string spell[10];

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

set<string> spellset;

string ans;

void cast(int sy, int sx, int y, int x, int d, string word)
{
  if(spellset.count(word)){
    if(ans.size() < word.size() || ans.size() == word.size() && ans > word){
      ans = word;
    }
  } else {
    spellset.insert(word);
  }
  if(sy == y && sx == x) return;
  int ny = (y + dy[d] + h) % h, nx = (x + dx[d] + w) % w;
  cast(sy, sx, ny, nx, d, word + spell[y][x]);
  return;
}

int main()
{
  while(cin >> h >> w, h || w){
    spellset.clear();
    for(int i = 0; i < h; i++) cin >> spell[i];
    ans = "";
    for(int i = 0; i < h; i++){
      for(int j = 0; j < w; j++){
	string word = "";
	for(int k = 0; k < 8; k++){
	  int ny = (i + dy[k] + h) % h, nx = (j + dx[k] + w) % w;
	  cast(i, j, ny, nx, k, word + spell[i][j]);
	}
      }
    }
    cout << (ans.size() > 1 ? ans:"0") << endl;
  }
  return 0;
}