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<algorithm>
#include<cstdio>
#include<cmath>
#include<cctype>
#include<math.h>
#include<string>
#include<string.h>
#include<stack>
#include<queue>
#include<vector>
#include<utility>
#include<set>
#include<map>
#include<stdlib.h>
#include<iomanip>

using namespace std;

#define ll long long
#define ld long double
#define EPS 0.0000000001
#define INF 1e9
#define MOD 1000000007
#define rep(i,n) for(int i=0;i<(n);i++)
#define loop(i,a,n) for(i=a;i<(n);i++)
#define all(in) in.begin(),in.end()
#define shosu(x) fixed<<setprecision(x)

typedef vector<int> vi;
typedef vector<string> vs;
typedef pair<int,int> pii;

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

int main(void) {
  int i,j;
  int h, w;
  while(cin >> h >> w, h){
      vs s(h);
      rep(i,h) cin >> s[i];
      map<string,int> ma;
      rep(i,h)rep(j,w)rep(k,8){
          string t = "";
          t += s[i][j];
          int x = (i + dx[k] + h)%h;
          int y = (j + dy[k] + w)%w;
          while(x != i || y != j){
              t += s[x][y];
              ma[t]++;
              x = (x + dx[k] + h)%h;
              y = (y + dy[k] + w)%w;
          }
      }
      string ans = "";
      for(auto itr=ma.begin();itr!=ma.end();itr++){
          if(itr->second >= 2){
              string t = itr->first;
              if(ans.size() < t.size()) ans = t;
          }
      }
      if(ans == ""){
          cout << 0 << endl;
      }else{
          cout << ans << endl;
      }
  }
}

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

#define rep(i, n) for(int i = 0 ; i < n ; i++)

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

int H, W;
char field[11][21];
map<string, int> v;

void solve(int x, int y){
  rep(i, 8){
    string s = "";
    s += field[y][x];
    bool used[11][21];
    memset(used, false, sizeof(used));
    used[y][x] = true;
    int nx = x+dx[i], ny = y+dy[i];
    while(true){
      if(nx < 0) nx = W-1;
      else if(nx >= W) nx = 0;
      if(ny < 0) ny = H-1;
      else if(ny >= H) ny = 0;      
      if(used[ny][nx]) break;
      used[ny][nx] = true;
      s += field[ny][nx];
      nx += dx[i], ny += dy[i];
      if(s.size() >= 2) v[s]++;
    }    
  }
}

int main(){
  while(cin >> H >> W, H|W){
    v.clear();
    rep(i, H) cin >> field[i];        

    rep(i, H) rep(j, W) solve(j, i);
    
    string ans = "";
    int L = 0;
    for(map<string, int>::iterator it = v.begin() ; it != v.end() ; it++){
      if(it->second < 2) continue;

      if(it->first.size() > L){
	L = it->first.size();
	ans = it->first;
      }
      else if(it->first.size() == L && ans > it->first) ans = it->first;
    }
    if(ans.size() == 0) cout << "0" << endl;
    else cout << ans << endl;
  }
  return 0;
}

C++: #include<iostream>
#include<vector>
#include<cstring>
using namespace std;

int lcm(int a, int b){
  return a/gcd(a, b) * b;
}

int main(int argc, char *argv[]){
  int w, h;
  while(cin >> h >> w, h){
    string torus[30];
    string s[2222];
    for (int i = 0; i < h; i++) {
      cin >> torus[i];
    }
    int l = lcm(w, h);
    int num = 0;
    for (int i = 0; i < h; i++) {
      for (int j = 0; j < w; j++) {
        for (int k = 0; k < h; k++) {
          s[num].push_back(torus[(h + i + k)%h][j]);
          s[num + 1].push_back(torus[(h + i - k)%h][j]);
        }
        
        for (int k = 0; k < w; k++) {
          s[num + 2].push_back(torus[i][(w + j + k)%w]);
          s[num + 3].push_back(torus[i][(w + j - k)%w]);
        }
        
        for (int k = 0; k < l; k++) {
          s[num + 4].push_back(torus[(l*h + i + k)%h][(l*w + j + k)%w]);
          s[num + 5].push_back(torus[(l*h + i - k)%h][(l*w + j + k)%w]);
          s[num + 6].push_back(torus[(l*h + i + k)%h][(l*w + j - k)%w]);
          s[num + 7].push_back(torus[(l*h + i - k)%h][(l*w + j - k)%w]);
        }
        num += 8;
      }
    }
    sort(s, s + 8*w*h);
    string ans = s[0];
    for (int i = 0; i < 8*w*h - 1; i++) {
      int length = 0;
      for (int j = 0;
           j < min(s[i].length(), s[i + 1].length()) - 1; j++) {
        if(s[i][length] == s[i + 1][length])length++;
        else break;
      }
      if(length > ans.length())ans = s[i].substr(0,length);
    }
    if(ans.length() > 1)std::cout << ans << std::endl;
    else std::cout << 0 << std::endl;
  }
  return 0;
}

C++: #include<bits/stdc++.h>
using namespace std;

#define int long long
typedef pair<int,int>pint;
typedef vector<int>vint;
typedef vector<pint>vpint;
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define all(v) (v).begin(),(v).end()
#define rep(i,n) for(int i=0;i<(n);i++)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
template<class T,class U>inline void chmin(T &t,U f){if(t>f)t=f;}
template<class T,class U>inline void chmax(T &t,U f){if(t<f)t=f;}

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

int H,W;
char fld[50][50];
void solve(){
    rep(i,H)cin>>fld[i];
    map<string,int>M;
    rep(i,H)rep(j,W)rep(d,8){
        int y=i,x=j;
        string hoge;
        do{
            hoge.pb(fld[y][x]);
            if(hoge.size()>1)M[hoge]++;
            y=(y+dy[d]+H)%H;
            x=(x+dx[d]+W)%W;
        }while(x!=j||y!=i);
    }
    string ans;
    each(it,M){
        if(it->se<=1)continue;
        if(ans.size()<it->fi.size())ans=it->fi;
        else if(ans.size()==it->fi.size())chmin(ans,it->fi);
    }
    if(ans=="")cout<<0<<endl;
    else cout<<ans<<endl;
}

signed main(){
    while(cin>>H>>W,H||W)solve();
    return 0;
}