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 <cstdio>
#include <cstdlib>
#include <cstring>
#include <climits>
#include <cassert>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <algorithm>
#include <numeric>
#include <complex>
#include <stack>
#include <queue>
#include <list>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <bitset>
#include <functional>
#include <iterator>

using namespace std;

#define dump(n) cout<<"# "<<#n<<'='<<(n)<<endl
#define repi(i,a,b) for(int i=int(a);i<int(b);i++)
#define peri(i,a,b) for(int i=int(b);i-->int(a);)
#define rep(i,n) repi(i,0,n)
#define per(i,n) peri(i,0,n)
#define foreach(i,c) for(auto i=(c).begin();i!=(c).end();++i)
#define all(c) begin(c),end(c)
#define mp make_pair

typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef vector<string> vs;
typedef pair<int,int> pii;

const int INFTY=1<<29;
const double EPS=1e-9;

template<typename T1,typename T2>
ostream& operator<<(ostream& os,const pair<T1,T2>& p){
	return os<<'('<<p.first<<','<<p.second<<')';
}
template<typename T>
ostream& operator<<(ostream& os,const vector<T>& a){
	os<<'[';
	rep(i,a.size()) os<<(i?" ":"")<<a[i];
	return os<<']';
}

int main()
{
	for(int h,w;cin>>h>>w,h|w;){
		vs d(h);
		rep(i,h) cin>>d[i];
		
		vs ss;
		rep(i0,h) rep(j0,w) rep(k,8){
			int di[]={-1,-1,-1,0,0,1,1,1};
			int dj[]={-1,0,1,-1,1,-1,0,1};
			string s;
			vvi vis(h,vi(w));
			for(int i=i0,j=j0;!vis[i][j];i=(i+di[k]+h)%h,j=(j+dj[k]+w)%w)
				s+=d[i][j],vis[i][j]=1;
			ss.push_back(s);
		}
		
		map<string,int> cnt;
		for(string s:ss)
			rep(i,s.size())
				cnt[s.substr(0,s.size()-i)]++;
		
		string res;
		for(auto kv:cnt)
			if(kv.second>=2 && res.size()<kv.first.size())
				res=kv.first;
		
		cout<<res<<endl;
	}
}

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


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

        vector<string> cand;
        for (int y = 0; y < H; y++) {
            for (int x = 0; x < W; x++) {
                for (int dx = -1; dx <= 1; dx++) {
                    for (int dy = -1; dy <= +1; dy++) {
                        if (dx == 0 && dy == 0) continue;
                        bool visited[15][25] = { 0 };
                        int nx = x, ny = y;
                        string spell;
                        while (!visited[ny][nx]) {
                            visited[ny][nx] = true;
                            spell += field[ny][nx];
                            cand.push_back(spell);
                            nx = (nx + dx + W) % W;
                            ny = (ny + dy + H) % H;
                        }
                    }
                }
            }
        }
        
        string ans = "";
        sort(cand.begin(), cand.end());
        for (int i = 1; i < (int)cand.size(); ++i) {
            if (cand[i].size() == 1) continue;
            if (cand[i] != cand[i - 1]) continue;
            if (ans.size() < cand[i].size() || ans > cand[i]) {
                ans = cand[i];
            }
        }
        if (ans == "") ans = "0";
        cout << ans << endl;
    }
}

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

using namespace std;

using lint = long long;
using ldouble = long double;

const vector<int> dx({-1, -1, -1, 0, 0, 1, 1, 1});
const vector<int> dy({-1, 0, 1, -1, 1, -1, 0, 1});

bool solve() {
    int h, w;
    cin >> h >> w;
    if (h == 0) return false;

    vector<string> torus(h);
    for (auto& s : torus) cin >> s;

    string ans = "0";
    set<string> app;

    function<void(int, int, int, vector<vector<bool>>&, string)> dfs =
        [&](int x, int y, int d, vector<vector<bool>>& used, string s) {
            if (used[x][y]) return;
            used[x][y] = true;

            s.push_back(torus[x][y]);
            if (s.length() > 1 && app.count(s) &&
                ((ans.length() < s.length()) ||
                 (ans.length() == s.length() && s < ans))) {
                ans = s;
            }
            app.insert(s);

            x = (x + dx[d] + h) % h;
            y = (y + dy[d] + w) % w;
            dfs(x, y, d, used, s);
        };

    for (int x = 0; x < h; ++x) {
        for (int y = 0; y < w; ++y) {
            for (int d = 0; d < 8; ++d) {
                vector<vector<bool>> used(h, vector<bool>(w, false));
                dfs(x, y, d, used, "");
            }
        }
    }

    cout << ans << endl;
    return true;
}

int main() {
    while (solve()) {}
    return 0;
}

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

int gcd(int a, int b){
  if(b == 0)return a;
  return gcd(b, a%b);
}

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