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 <string>
#include <algorithm>
using  namespace std;

int dr[]={-1, -1, -1, 0, 0, 1, 1, 1};
int dc[]={-1, 0, 1, -1, 1, -1, 0, 1};

bool cmp(const string& a, const string& b)
{
    if (a.size()<b.size()) return false;
    if (a.size()>b.size()) return true;
    return a<b;
}

int main()
{
    int n, m;
    while (scanf("%d%d", &n, &m), n) {
        char s[11][21];
        for(int i=0;i<n;++i) scanf("%s", s[i]);

        vector<string> spells;
        for(int i=0;i<n;++i) for(int j=0;j<m;++j) for(int k=0;k<8;++k) {
            int r=i, c=j, q=0;
            string t;
            do {
                t+=s[r][c];
                if (t.size()>1) spells.push_back(t);
                r=(r+dr[k]+2*n)%n;
                c=(c+dc[k]+2*m)%m;
            } while (r!=i || c!=j);
        }
        sort(begin(spells), end(spells), cmp);

        string res;
        for(int i=1;i<spells.size();++i) if (spells[i]==spells[i-1]) {
            res=spells[i];
            break;
        }
        puts(res.size()?res.c_str():"0");
    }
    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 <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

int h, w;
void solve(int y, int x, vector<string> const& v, vector<string>& ret) {
    int dx[8] = {0, 1, 1, 1, 0, -1, -1, -1},
        dy[8] = {-1, -1, 0, 1, 1, 1, 0, -1};
    for(int i=0; i<8; ++i) {
        string s;
        vector<vector<bool>> used(h, vector<bool>(w, false));
        while(!used[y][x]) {
            s += v[y][x];
            used[y][x] = true;
            x = (x + dx[i] + w)%w;
            y = (y + dy[i] + h)%h;
            if(s.size() >= 2) {
                ret.push_back(s);
            }
        }
    }
}

int main() {
    while(cin >> h >> w, h) {
        vector<string> v(h);
        vector<string> ret;
        for(int i=0; i<h; ++i) {
            cin >> v[i];
        }
        for(int i=0; i<h; ++i) {
            for(int j=0; j<w; ++j) {
                solve(i, j, v, ret);
            }
        }
        sort(ret.begin(), ret.end());
        string ret2;
        for(int i=0; i<ret.size()-1; ++i) {
            if(ret[i] == ret[i+1]) {
                if(ret2.size() < ret[i].size() || ret2.size() == ret[i].size() && ret2 > ret[i]) {
                    ret2 = ret[i];
                }
            }
        }
        if(ret2.size() == 0) {
            cout << 0 << endl;
        } else {
            cout << ret2 << endl;
        }
    }   
}

C++: #include <bits/stdc++.h>
using namespace std;
#define REP(i, s, e) for(int i = (int)(s); i < (int)(e); ++i)
#define rep(i, n) REP(i, 0, n)
int main() {
  int h, w;
  while(cin >> h >> w) {
    if(h == 0 && w == 0) break;
    vector<string> s(h);
    rep(i, h) cin >> s[i];
    map<string, int> mp;
    rep(i, h) rep(j, w) {
      REP(dx, -1, 2) REP(dy, -1, 2) {
	if(dx == 0 && dy == 0) continue;
	//cout << i << " " << j << " " << dy << " " << dx << endl;
	string tmp;
	tmp += s[i][j];
	int x = (j + dx + w) % w;
	int y = (i + dy + h) % h;
	while(1) {
	  // cout << y << " " << x << endl; 
	  if(x == j && y == i) break;
	  tmp += s[y][x];
	  x = (x + dx + w) % w;
	  y = (y + dy + h) % h;
	  mp[tmp]++;
	}
	// mp[tmp]++;
	// cout << i << " " << j << " " << dy << " " << dx << " " << tmp << endl;
      }
    }
    string ans;
    for(const auto& p : mp) {
      if(p.second == 1) continue;
      if(ans.size() < p.first.size()) ans = p.first;
      else if(ans.size() == p.first.size()) {
	ans = min(ans, p.first);
      }
    }
    if(ans == "") cout << 0 << endl;
    else cout << ans << endl;
  }
  return 0;
}