#include <iostream>
#include <map>
#include <vector>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;

struct P{
    int x;
    int y;
    P() {}
    ~P() {}
    P(const P& r) : x(r.x), y(r.y) {}
    P(int a, int b) : x(a), y(b) {}
};

struct Q{
    string spell;
    P pos; vector<P> visited;
    int dir;
    Q() {}
    ~Q() {}
    Q(const Q& r) : spell(r.spell), pos(r.pos),
                    visited(r.visited), dir(r.dir) {}
    Q(string s, P p, vector<P> v, int d) : spell(s), pos(p),
                                                   visited(v), dir(d) {} };

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

int main(){
    int h, w, x, y, z;
    for(; cin >> h >> w, h||w;){
        char field[20][20];
        map<string, int> found;
        for(char c = 'A'; c <= 'Z'; c++){
            found[ string(1, c) ] = 0;
        }
        queue< Q > que;
        vector<P> EMPTY(100);
        for(x = 0; x < h; x++){
            scanf(" %s", field[x]);
            for(y = 0; y < w; y++){
                found[ string(1, field[x][y]) ]++;
                que.push( Q( string(1, field[x][y]), P(x, y), EMPTY, 0) );
                que.push( Q( string(1, field[x][y]), P(x, y), EMPTY, 1) );
                que.push( Q( string(1, field[x][y]), P(x, y), EMPTY, 2) );
                que.push( Q( string(1, field[x][y]), P(x, y), EMPTY, 3) );
                que.push( Q( string(1, field[x][y]), P(x, y), EMPTY, 4) );
                que.push( Q( string(1, field[x][y]), P(x, y), EMPTY, 5) );
                que.push( Q( string(1, field[x][y]), P(x, y), EMPTY, 6) );
                que.push( Q( string(1, field[x][y]), P(x, y), EMPTY, 7) );
            }
        }
        string best = "0";
        for(int l = 1;; l++){
            while(true){
                if( que.empty() ) break;
                Q q = que.front();
                if( q.spell.size() != l ) break;
                que.pop();
                if( found[ q.spell ] < 2 ) continue;
                if( q.spell.size() > best.size() ||
                        (q.spell.size() == best.size() && q.spell < best) ){
                    best = q.spell;
                }
                int cx = q.pos.x, cy = q.pos.y, d = q.dir;
                int nx = (cx + dx[d] + h) % h, ny = (cy + dy[d] + w) % w;
                bool ok = true;
                for(vector<P>::iterator it = q.visited.begin();
                        it != q.visited.end(); it++){
                    if( (it->x == nx) && (it->y == ny) ){
                        ok = false;
                        break;
                    }
                }
                if( ok ){
                    string ns = q.spell;
                    ns.append(1, field[nx][ny]);
                    vector<P> nv = q.visited;
                    nv.push_back( P(cx, cy) );
                    que.push( Q( ns, P(nx, ny), nv, d ) );
                    if( found.find(ns) == found.end() ){
                        found[ns] = 1;
                    }else{
                        found[ns] ++;
                    }
                }
            }
            if( que.empty() ) break;
        }
        cout << best << endl;
    }
    return 0;
}

Measured memory_bytes: 7824