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++: /*
 * GCA : "Computer is artificial subject absolutely,Math is God"
 */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <climits>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <cctype>
#include <utility>
#include <ctime>
using namespace std;
#ifdef DEBUG
#define VAR(a,b) __typeof(b) a=(b)
#define debug(...) printf("DEBUG: "),printf(__VA_ARGS__)
#else
#define VAR(a,b) __typeof(b) a=(b)
#define debug(...)
#endif
typedef unsigned int uint;
typedef long long int Int;
typedef unsigned long long int UInt;
#define Set(a,s) memset(a,s,sizeof(a))
#define Pln() printf("\n")
#define For(i,x)for(int i=0;i<x;i++)
#define CON(x,y) x##y
#define M 25
#define PB push_back
#define oo INT_MAX
#define FOR(a,b) for(VAR(a,(b).begin());a!=(b).end();++a)
#define eps 1e-9
#define X first
#define Y second
inline bool xdy(double x,double y){return x>y+eps;}
inline bool xddy(double x,double y){return x>y-eps;}
inline bool xcy(double x,double y){return x<y-eps;}
inline bool xcdy(double x,double y){return x<y+eps;}
const Int mod=1000000007;
int nx,ny;
char mz[M][M];
set<Int> sid;
int dx[8]={0,1,1,1,0,-1,-1,-1};
int dy[8]={1,1,0,-1,-1,-1,0,1};
char store[M*M];
int ox,oy;
string ans;
Int isid;
bool vis[M][M];
void dfs(int x,int y,int d,int dep){

	store[dep]=mz[y][x];
	int nex=(x+dx[d]+nx)%nx;
	int ney=(y+dy[d]+ny)%ny;
	store[dep+1]=0;
	isid=130*isid+store[dep];
	string ss(store);
	if(sid.count(isid)&&ss.length()>=2){
		if(ss.length()>ans.length())ans=ss;
		else if(ss.length()==ans.length()&&ss<ans){
			ans=ss;
		}
	}
	sid.insert(isid);
	vis[x][y]=1;
	if(!vis[nex][ney])dfs(nex,ney,d,dep+1);
	vis[x][y]=0;

}
void solve(){
	Set(vis,0);
	for(int i=0;i<ny;i++){
		for(int j=0;j<nx;j++){
			for(int k=0;k<8;k++){
				isid=0;
				vis[j][i]=1;
				dfs(j,i,k,0);
				vis[j][i]=0;
			}
		}
	}
	if(ans.size())
		puts(ans.c_str());
	else puts("0");
}
int main() {
	ios_base::sync_with_stdio(0);
	while(~scanf("%d%d",&ny,&nx)&&ny&&nx){
		sid.clear();
		ans="";
		for(int i=0;i<ny;i++)scanf("%s",mz[i]);
		solve();

	}

















}

C++: #include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std;

char s[1605][203];
char ans[203],sp[203];
char mp[11][22];
int maxv,h,w,indx,mx[8]={1,-1,0,0,1,-1,1,-1},my[8]={0,0,1,-1,1,-1,-1,1};

struct node
{
    int num;
    node *next[26];
    node(){num=0;for(int i=0;i<26;i++)next[i]=NULL;}
};

node *root;

void update(node *head,int i,int j)
{
    head->num++;
    if(s[i][j]=='\0')return;
    if(head->next[s[i][j]-'A']==NULL)
    {
        head->next[s[i][j]-'A']=new node();
    }
    update(head->next[s[i][j]-'A'],i,j+1);
}

void refresh(int depth)
{
    if(depth>maxv)
    {
        int i;
        maxv=depth;
        for(i=0;i<depth;i++)
        ans[i]=sp[i];
        ans[i]='\0';
    }
}

void dfs(node *head,int depth)
{
    if(head==NULL)
         refresh(depth-1);
    else if((head->num)<2)
         refresh(depth-2);
    else
    {
        int i;
        for(i=0;i<26;i++)
        {
            sp[depth]=i+'A';
            dfs(head->next[i],depth+1);
        }
    }
}

void getstr(int x,int y)
{
  int i,j,k,p;
  for(k=0;k<8;k++)
  {
      s[indx][0]=mp[x][y];
      i=x+mx[k];
      j=y+my[k];
      i=(i+h)%h;
      j=(j+w)%w;
      p=1;
      while(i!=x||j!=y)
      {
          s[indx][p++]=mp[i][j];
          i+=mx[k];
          j+=my[k];
          i=(i+h)%h;
          j=(j+w)%w;
      }
      s[indx][p]='\0';
      //cout <<s[indx]<<endl;
      indx++;
  }
}

int main()
{
    int i,j;
    freopen("B.out","w",stdout);
    while(scanf("%d %d",&h,&w)!=EOF&&(h!=0||w!=0))
    {
        root=new node;
        indx=0;
        maxv=-1;
        for(i=0;i<h;i++)
            scanf("%s",mp[i]);
        for(i=0;i<h;i++)
         for(j=0;j<w;j++)
         {
             getstr(i,j);
         }
        for(i=0;i<indx;i++)update(root,i,0);
        dfs(root,0);
        if(strlen(ans)!=1)printf("%s\n",ans);
        else printf("0\n");
    }
    return 0;
}

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

using namespace std;
#define loop(i,a,b) for(int i=(a);i<int(b);i++)
#define rep(i,b) loop(i,0,b)

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

string g[100];

int h,w;
int main(){
    while(cin>>h>>w && h){
        vector<string> v;
        rep(i,h)cin>>g[i];
        rep(i,h)rep(j,w){
            rep(d,4){
                string s;
                for(int ii=i, jj=j; s.size()==0 || ii!=i || jj!=j;
                    ii=(ii+h+dy[d])%h, jj=(jj+w+dx[d])%w){
                    s += g[ii][jj];
                    if(s.size()==1) continue;
                    v.push_back(s);
                    reverse(s.begin(),s.end());
                    v.push_back(s);
                    reverse(s.begin(),s.end());
                }
            }
        }

        sort(v.rbegin(),v.rend(),[](const string& s, const string& t){
                if(s.size()==t.size()) return s>t;
                return s.size()<t.size();
            });

        string ans="";
        rep(i,v.size()-1){
            if(v[i]==v[i+1]){
                ans=v[i];
                break;
            }
        }
        if(ans=="")ans="0";
        cout<<ans<<endl;
    }
}