#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<climits>
#include<iomanip>
#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
using namespace std;
int dx[] = {+0,+1,+0,-1,+1,+1,-1,-1};
int dy[] = {+1,+0,-1,+0,-1,+1,-1,+1};
int H,W;
map<string,int> cnt;
string ans;
vector<string> vec;

/*
void compareS(string &a,string b)
{
  int as = a.size();
  int bs = b.size();
  if(bs < 2)return;
  cnt[a]++,cnt[b]++;
  if(cnt[b] < 2)return;
  if(as > bs)return;
  if(as != bs)a = (as < bs)?b:a;
    a = min(a,b);
}
*/

void dfs(string *G,bool used[][20],int x,int y,int dir,string s)
{
  if(used[y][x])return;
  used[y][x] = true;
  //compareS(ans,s);
  if(s.size() >= 2)vec.push_back(s);
  int nx = (x+dx[dir]+W)%W, ny = (y+dy[dir]+H)%H;
  dfs(G,used,nx,ny,dir,s+G[ny][nx]);
}

int main()
{
  //clock_t s,t;
  //s = clock();
  while(cin >> H >> W,H|W)
    {
      vec.clear();
      cnt.clear();
      string G[H];
      rep(i,H)
	cin >> G[i];

      ans = "";
      rep(i,H)
	{
	  rep(j,W)
	    {
	      rep(k,8)
		{
		  bool used[10][20];
		  rep(a,H)rep(b,W)used[a][b] = false;		 
		  dfs(G,used,j,i,k,string(1,G[i][j]));
		}
	    }
	}
	  
      
      sort(vec.begin(),vec.end());
      rep(i,vec.size()-1)
	{
	  if(vec[i] == vec[i+1])
	    {
	      int vs = vec[i].size();
	      int as = ans.size();
	      if(vs < as)continue;
	      if(vs != as)ans = (as < vs)?vec[i]:ans;
	      else        ans = min(ans,vec[i]);
	      i++;
	    }
	}
      
	ans == ""?cout << 0 << endl:cout << ans << endl;

    }
  //t = clock();
  //cout << setiosflags(ios::fixed) << setprecision(10) << (double)(t-s)/CLOCKS_PER_SEC << endl;
  return 0;
}