Problem:
Problem B:
The Sorcerer's Donut
Your master went to the town for a day. You could have a relaxed day without hearing his
scolding. But he ordered you to make donuts dough by the evening. Loving donuts so much, he
can't live without eating tens of donuts everyday. What a chore for such a beautiful day.
But last week, you overheard a magic spell that your master was using. It was the time to
try. You casted the spell on a broomstick sitting on a corner of the kitchen. With a flash of
lights, the broom sprouted two arms and two legs, and became alive. You ordered him, then he
brought flour from the storage, and started kneading dough. The spell worked, and how fast he
kneaded it!
A few minutes later, there was a tall pile of dough on the kitchen table. That was enough for
the next week. \OK, stop now." You ordered. But he didn't stop. Help! You didn't know the
spell to stop him! Soon the kitchen table was filled with hundreds of pieces of dough, and he
still worked as fast as he could. If you could not stop him now, you would be choked in the
kitchen filled with pieces of dough.
Wait, didn't your master write his spells on his notebooks? You went to his den, and found the
notebook that recorded the spell of cessation.
But it was not the end of the story. The spell written in the notebook is not easily read by
others. He used a plastic model of a donut as a notebook for recording the spell. He split the
surface of the donut-shaped model into square mesh (Figure B.1), and filled with the letters
(Figure B.2). He hid the spell so carefully that the pattern on the surface looked meaningless.
But you knew that he wrote the pattern so that the spell "appears" more than once (see the next
paragraph for the precise conditions). The spell was not necessarily written in the left-to-right
direction, but any of the 8 directions, namely left-to-right, right-to-left, top-down, bottom-up,
and the 4 diagonal directions.
You should be able to find the spell as the longest string that appears more than once. Here,
a string is considered to appear more than once if there are square sequences having the string
on the donut that satisfy the following conditions.
Each square sequence does not overlap itself. (Two square sequences can share some squares.)
The square sequences start from different squares, and/or go to different directions.
Figure B.1: The Sorcerer's Donut Before
Filled with Letters, Showing the Mesh and 8
Possible Spell Directions
Figure B.2: The Sorcerer's Donut After Filled
with Letters
Note that a palindrome (i.e., a string that is the same whether you read it backwards or forwards)
that satisfies the first condition "appears" twice.
The pattern on the donut is given as a matrix of letters as follows.
ABCD
EFGH
IJKL
Note that the surface of the donut has no ends; the top and bottom sides, and the left and right
sides of the pattern are respectively connected. There can be square sequences longer than both
the vertical and horizontal lengths of the patt
...(truncated)

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using a2 = array<int, 2>;
using a3 = array<ll, 3>;

bool chmin(auto& a, const auto& b) { return a > b ? a = b, 1 : 0; }
bool chmax(auto& a, const auto& b) { return a < b ? a = b, 1 : 0; }

ll mod = 998244353;
const ll INF = 1e18;

ifstream in;
ofstream out;

int main(int argc, char** argv) {
    ios::sync_with_stdio(false);
    cin.tie(0);

    if(argc > 2) {
        in.open(argv[1]);
        cin.rdbuf(in.rdbuf());
        out.open(argv[2]);
        cout.rdbuf(out.rdbuf());
    }

    while(1) {
        ll h, w;
        cin >> h >> w;
        if(h == 0) break;

        vector<string> v(h);
        for(auto& x : v) cin >> x;

        map<string, ll> mp;

        vector<a2> dir = {
            {1, 0}, {-1, 0}, {0, 1},  {0, -1},
            {1, 1}, {1, -1}, {-1, 1}, {-1, -1},
        };
        for(int i = 0; i < h; i++) {
            for(int j = 0; j < w; j++) {
                for(auto [dx, dy] : dir) {
                    ll p = (i + h + dx) % h, q = (j + w + dy) % w;
                    string s(1, v[i][j]);
                    while(p != i || q != j) {
                        s.push_back(v[p][q]);
                        mp[s]++;
                        p = (p + h + dx) % h, q = (q + w + dy) % w;
                    }
                }
            }
        }

        ll len = 0;
        string ans;
        for(auto [s, cnt] : mp) {
            if(cnt > 1) {
                if(chmax(len, s.size())) {
                    ans = s;
                }
            }
        }

        if(len == 0) {
            cout << 0 << endl;
        } else {
            cout << ans << endl;
        }
    }

    return 0;
}
accuracy: 1
time_ms: 250
memory_kb: 30080
final_rank: 5

code_snippet: #include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <map>
#include <vector>
#include <algorithm>

using namespace std;

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

int n, m, ml, cnt;
char donut[maxn][maxn];
string ans[2000];
map<string, int> mp;

int main()
{
#ifdef LOCAL
	freopen("B.in", "r", stdin);
#endif
	while(scanf("%d%d", &n, &m) != EOF) {
		if(n == 0 && m == 0)	break;
		ml = cnt = 0;
		mp.clear();
		for(int i = 0; i < n; i++)
			scanf("%s", donut[i]);
		for(int i = 0; i < n; i++)
			for(int j = 0; j < m; j++) 
				for(int k = 0; k < 8; k++) {
					string tmp = "";
					int nx = i, ny = j;
					do{
						tmp += donut[nx][ny];
						if(tmp.size() >= 2 && tmp.size() >= ml) {
							if(!mp[tmp])	mp.insert(pair <string, int> (tmp, 1));	
							else if(tmp.size() == ml && mp[tmp] == 1) 
								ans[cnt++] = tmp;
							else if(tmp.size() > ml) {
								ml = tmp.size();
								cnt = 0;
								ans[cnt++] = tmp;
							}
						}
						mp[tmp]++;						
						nx = (nx+dx[k]+n)%n;
						ny = (ny+dy[k]+m)%m;
					}while(nx != i || ny != j);	
//					cout << tmp << endl;	
					/*
					if(!mp[tmp])	mp.insert(pair <string, int> (tmp, 1));	
					else {
						if(tmp.size() == ml && mp[tmp] == 1) {
							ans[cnt++] = tmp;
						}
						else if(tmp.size() > ml) {
							ml = tmp.size();
							cnt = 0;
							ans[cnt++] = tmp;
						}
						mp[tmp]++;
					}
					*/
				}
		sort(ans, ans+cnt);
		if(cnt)	printf("%s\n", ans[0].c_str());
		else	printf("0\n");
	}
	return 0;
}
accuracy: 1
time_ms: 410
memory_kb: 30120
final_rank: 16

code_snippet: #include<bits/stdc++.h>
// #include<atcoder/all>
// #include<boost/multiprecision/cpp_int.hpp>

using namespace std;
// using namespace atcoder;
// using bint = boost::multiprecision::cpp_int;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
using vi = vector<ll>;
using vvi = vector<vi>;
using vvvi = vector<vvi>;
using ve = vector<vector<int>>;
using vb = vector<bool>;
using vvb = vector<vb>;
#define rep(i,s,n) for(ll i = (ll)s;i < (ll)n;i++)
#define rrep(i,l,r) for(ll i = r-1;i >= l;i--)
#define ALL(x) (x).begin(),(x).end()
#define sz(c) ((ll)(c).size())
#define LB(A,x) (int)(lower_bound(A.begin(),A.end(),x)-A.begin())
#define UB(A,x) (int)(upper_bound(A.begin(),A.end(),x)-A.begin())
// #define MOD 1000000007
#define MOD 998244353
template<typename T>using min_priority_queue=priority_queue<T,vector<T>,greater<T>>;
template<typename T>ostream&operator<<(ostream&os,vector<T>&v){for(int i = 0;i < v.size();i++)os<<v[i]<<(i+1!=v.size()?" ":"");return os;}
template<typename T>istream&operator>>(istream&is,vector<T>&v){for(T&in:v)is>>in;return is;}
template<typename T1,typename T2>ostream&operator<<(ostream&os,pair<T1,T2>&p){os<<p.first<<" "<<p.second;return os;}
template<typename T1,typename T2>istream&operator>>(istream&is,pair<T1,T2>&p){is>>p.first>>p.second;return is;}
template<typename T> inline bool chmax(T &a,T b){if(a < b){a = b;return true;}return false;}
template<typename T> inline bool chmin(T &a,T b){if(a > b){a = b;return true;}return false;}
ld dist(ld x1,ld y1,ld x2, ld y2){return sqrtl((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));}

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

int main(){
  
  ios_base::sync_with_stdio(0), cin.tie(0);
  while(1){
    int h,w;cin >> h >> w;
    if(!h)break;
    vector<string> s(h);cin >> s;
    string res = "0";
    unordered_set<string> st;
    rep(i,0,h)rep(j,0,w)rep(dir,0,8){
      string t = "";
      t += s[i][j];
      int ni = (i+dy[dir]+h)%h,nj = (j+dx[dir]+w)%w;
      while(ni != i || nj != j){
        t += s[ni][nj];
        if(st.count(t)){
          if(sz(t) > sz(res))res = t;
          else if(sz(t) == sz(res)){
            if(t < res)res = t;
          }
        }else st.insert(t);
        ni = (ni+dy[dir]+h)%h,nj = (nj+dx[dir]+w)%w;
      }
    }
    cout << res << "\n";
  }
  

  return 0;
}
accuracy: 1
time_ms: 290
memory_kb: 29480
final_rank: 4

code_snippet: #include <iostream>
#include <iomanip>
#include <cassert>
#include <vector>
#include <algorithm>
#include <utility>
#include <numeric>
#include <tuple>
#include <ranges>
namespace ranges = std::ranges;
namespace views = std::views;
// #include "Src/Number/IntegerDivision.hpp"
// #include "Src/Utility/BinarySearch.hpp"
// #include "Src/Sequence/CompressedSequence.hpp"
// #include "Src/Sequence/RunLengthEncoding.hpp"
// #include "Src/Algebra/Group/AdditiveGroup.hpp"
// #include "Src/DataStructure/FenwickTree/FenwickTree.hpp"
// #include "Src/DataStructure/SegmentTree/SegmentTree.hpp"
// using namespace zawa;
// #include "atcoder/modint"
// using mint = atcoder::modint998244353;
#include <set>
int H, W;
std::string S[10];
bool solve() {
    std::cin >> H >> W;
    if (H == 0 and W == 0) return false;
    for (int i = 0 ; i < H ; i++) std::cin >> S[i];
    std::vector<std::string> app;
    for (int sy = 0 ; sy < H ; sy++) for (int sx = 0 ; sx < W ; sx++) {
        for (int dy = -1 ; dy <= 1 ; dy++) for (int dx = -1 ; dx <= 1 ; dx++) if (dy != 0 or dx != 0) {
            std::set<std::pair<int, int>> vis;
            std::string T;
            for (int d = 0 ; ; d++) {
                const int py = ((sy + d * dy) % H + H) % H;
                const int px = ((sx + d * dx) % W + W) % W;
                if (vis.contains(std::pair{py, px})) break;
                vis.insert({py, px});
                T += S[py][px];
                if (T.size() >= 2u) app.push_back(T);
            }
        }
    }
    ranges::sort(app);
    std::vector<std::string> multiple;
    for (int i = 0, j = 0 ; i < std::ssize(app) ; i = j) {
        while (j < std::ssize(app) and app[i] == app[j]) j++;
        if (j - i >= 2) multiple.push_back(app[i]);
    }
    std::vector<std::string> ans;
    for (int i = 0 ; i < std::ssize(multiple) ; i++) {
        auto it = ranges::lower_bound(multiple.begin() + i + 1, multiple.end(), multiple[i]);
        if (it == multiple.end() or it->size() < multiple[i].size() or it->substr(0, multiple[i].size()) != multiple[i])
            ans.push_back(multiple[i]);
    }
    if (ans.empty()) std::cout << 0 << '\n';
    else {
        int idx = 0;
        for (int i = 1 ; i < std::ssize(ans) ; i++) if (ans[idx].size() < ans[i].size()) idx = i;
        std::cout << ans[idx] << '\n';
    }
    return true;
}
int main() {
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);
    std::ios::sync_with_stdio(false);
    while (solve()) std::cout.flush();
}
accuracy: 1
time_ms: 290
memory_kb: 31208
final_rank: 14

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

#include <unistd.h>

namespace fastio {
static constexpr uint32_t SZ = 1 << 17;
char ibuf[SZ];
char obuf[SZ];
char out[100];
// pointer of ibuf, obuf


uint32_t pil = 0, pir = 0, por = 0;

struct Pre {
    char num[10000][4];
    constexpr Pre() : num() {
        for (int i = 0; i < 10000; i++) {
            int n = i;
            for (int j = 3; j >= 0; j--) {
                num[i][j] = n % 10 | '0';
                n /= 10;
            }
        }
    }
} constexpr pre;

inline void load() {
    memmove(ibuf, ibuf + pil, pir - pil);
    pir = pir - pil + fread(ibuf + pir - pil, 1, SZ - pir + pil, stdin);
    pil = 0;
    if (pir < SZ)
        ibuf[pir++] = '\n';
}

inline void flush() {
    fwrite(obuf, 1, por, stdout);
    por = 0;
}

void rd(char &c) {
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
}

void rd(string &x) {
    x.clear();
    char c;
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
    do {
        x += c;
        if (pil == pir)
            load();
        c = ibuf[pil++];
    } while (!isspace(c));
}

template <typename T> void rd_real(T &x) {
    string s;
    rd(s);
    x = stod(s);
}

template <typename T> void rd_integer(T &x) {
    if (pil + 100 > pir)
        load();
    char c;
    do
        c = ibuf[pil++];
    while (c < '-');
    bool minus = 0;
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (c == '-') {
            minus = 1, c = ibuf[pil++];
        }
    }
    x = 0;
    while ('0' <= c) {
        x = x * 10 + (c & 15), c = ibuf[pil++];
    }
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (minus)
            x = -x;
    }
}

void rd(int &x) {
    rd_integer(x);
}
void rd(ll &x) {
    rd_integer(x);
}
void rd(i128 &x) {
    rd_integer(x);
}
void rd(uint &x) {
    rd_integer(x);
}
void rd(ull &x) {
    rd_integer(x);
}
void rd(u128 &x) {
    rd_integer(x);
}
void rd(double &x) {
    rd_real(x);
}
void rd(long double &x) {
    rd_real(x);
}

template <class T, class U> void rd(pair<T, U> &p) {
    return rd(p.first), rd(p.second);
}
template <size_t N = 0, typename T> void rd_tuple(T &t) {
    if constexpr (N < std::tuple_size<T>::value) {
        auto &x = std::get<N>(t);
        rd(x);
        rd_tuple<N + 1>(t);
    }
}
template <class... T> void rd(tuple<T...> &tpl) {
    rd_tuple(tpl);
}

template <size_t N = 0, typename T> void rd(array<T, N> &x) {
    for (auto &d : x)
        rd(d);
}
template <class T> void rd(vector<T> &x) {
    for (auto &d : x)
        rd(d);
}

void read() {}
template <class H, class... T> void read(H &h, T &...t) {
    rd(h), read(t...);
}

void wt(const char c) {
    if (por == SZ)
        flush();
    obuf[por++] = c;
}
void wt(const string s) {
    for (char c : s)
        wt(c);
}
void wt(const char *s) {
    size_t len = strlen(s);
    for (size_t i = 0; i < len; i++)
        wt(s[i]);
}

template <typename T> void wt_integer(T x) {
    if (por > SZ - 100)
        flush();
    if (x < 0) {
        obuf[por++] = '-', x = -x;
    }
    int outi;
    for (outi = 96; x >= 10000; outi -= 4) {
        memcpy(out + outi, pre.num[x % 10000], 4);
        x /= 10000;
    }
    if (x >= 1000) {
        memcpy(obuf + por, pre.num[x], 4);
        por += 4;
    } else if (x >= 100) {
        memcpy(obuf + por, pre.num[x] + 1, 3);
        por += 3;
    } else if (x >= 10) {
        int q = (x * 103) >> 10;
        obuf[por] = q | '0';
        obuf[por + 1] = (x - q * 10) | '0';
        por += 2;
    } else
        obuf[por++] = x | '0';
    memcpy(obuf + por, out + outi + 4, 96 - outi);
    por += 96 - outi;
}

template <typename T> void wt_real(T x) {
    ostringstream oss;
    oss << fixed << setprecision(15) << double(x);
    string s = oss.str();
    wt(s);
}

void wt(int x) {
    wt_integer(x);
}
void wt(ll x) {
    wt_integer(x);
}
void wt(i128 x) {
    wt_integer(x);
}
void wt(uint x) {
    wt_integer(x);
}
void wt(ull x) {
    wt_integer(x);
}
void wt(u128 x) {
    wt_integer(x);
}
void wt(double x) {
    wt_real(x);
}
void wt(long double x) {
    wt_real(x);
}

template <class T, class U> void wt(const pair<T, U> val) {
    wt(val.first);
    wt(' ');
    wt(val.second);
}
template <size_t N = 0, typename T> void wt_tuple(const T t) {
    if constexpr (N < std::tuple_size<T>::value) {
        if constexpr (N > 0) {
            wt(' ');
        }
        const auto x = std::get<N>(t);
        wt(x);
        wt_tuple<N + 1>(t);
    }
}
template <class... T> void wt(tuple<T...> tpl) {
    wt_tuple(tpl);
}
template <class T, size_t S> void wt(const array<T, S> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}
template <class T> void wt(const vector<T> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}

void print() {
    wt('\n');
}
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail) {
    wt(head);
    if (sizeof...(Tail))
        wt(' ');
    print(forward<Tail>(tail)...);
}
void __attribute__((destructor)) _d() {
    flush();
}
} // namespace fastio


using fastio::flush;
using fastio::print;
using fastio::read;

inline void first(bool i = true) {
    print(i ? "first" : "second");
}
inline void Alice(bool i = true) {
    print(i ? "Alice" : "Bob");
}
inline void Takahashi(bool i = true) {
    print(i ? "Takahashi" : "Aoki");
}
inline void yes(bool i = true) {
    print(i ? "yes" : "no");
}
inline void Yes(bool i = true) {
    print(i ? "Yes" : "No");
}
inline void No() {
    print("No");
}
inline void YES(bool i = true) {
    print(i ? "YES" : "NO");
}
inline void NO() {
    print("NO");
}
inline void Yay(bool i = true) {
    print(i ? "Yay!" : ":(");
}
inline void Possible(bool i = true) {
    print(i ? "Possible" : "Impossible");
}
inline void POSSIBLE(bool i = true) {
    print(i ? "POSSIBLE" : "IMPOSSIBLE");
}

/**
 * @brief Fast IO
 */

int main() {
while(1) {
    int N, M;
    cin >> N >> M;
    if (N == 0 && M == 0) return 0;
    vector<vector<char>> C(N,vector<char>(M));
    rep(i,0,N) rep(j,0,M) cin >> C[i][j];\
    map<string,int> mp;
    rep(i,0,N) {
        rep(j,0,M) {
            rep(dx,-1,2) {
                rep(dy,-1,2) {
                    if (dx==0 && dy==0) continue;
                    vector<vector<bool>> used(N,vector<bool>(M,false));
                    int PX = i, PY = j;
                    string Cur = "";
                    while(1) {
                        if (used[PX][PY]) break;
                        Cur += C[PX][PY];
                        used[PX][PY] = true;
                        PX = (PX + N + dx) % N;
                        PY = (PY + M + dy) % M;
                    }
                    for (int k = 2; k <= Cur.size(); k++) {
                        mp[Cur.substr(0,k)]++;
                    }
                }
            }
        }
    }
    vector<string> S;
    for (auto it = mp.begin(); it != mp.end(); it++) {
        if (it->second >= 2) S.push_back(it->first);
    }
    string ANS = "";
    rep(i,0,S.size()) {
        if (ANS.size() < S[i].size()) ANS = S[i];
        else if (ANS.size() == S[i].size() && ANS > S[i]) ANS = S[i];
    }
    if (ANS == "") cout << 0 << endl;
    else cout << ANS << endl;
}
}
accuracy: 1
time_ms: 290
memory_kb: 32496
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;

bool solve() {
        int H, W; cin >> H >> W;
        if (H == 0 and W == 0) return false;
        vector<vector<char>> G(H, vector<char>(W));
        for (auto& g : G) for (auto& x : g) cin >> x;

        auto get = [&](int sy, int sx, int dy, int dx) -> string {
                vector<vector<bool>> used(H, vector<bool>(W, false));
                int ny = sy, nx = sx;
                string res{};
                while (!used.at(ny).at(nx)) {
                        res += G[ny][nx];
                        used[ny][nx] = true;
                        ny += dy; ny = (ny + H) % H;
                        nx += dx; nx = (nx + W) % W;
                }
                return res;
        };
        
        /*
        cout << get(4, 5, -1, 1) << endl;
        exit(0);
        */

        map<string, int> mp{};

        for (int sy = 0 ; sy < H ; sy++) {
                for (int sx = 0 ; sx < W ; sx++) {
                        for (int dy = -1 ; dy <= 1 ; dy++) {
                                for (int dx = -1 ; dx <= 1 ; dx++) {
                                        if (dy == 0 and dx == 0) continue;
                                        string s = get(sy, sx, dy, dx);
                                        for (size_t len = 2 ; len <= s.size() ; len++) {
                                                mp[s.substr(0, len)]++;
                                        }
                                }
                        }
                }
        }

        string ans{};
        for (const auto& [s, cnt] : mp) {
                if (cnt < 2) continue;
                if (ans.size() > s.size()) continue;
                if (ans.size() == s.size()) {
                        ans = min(ans, s);
                }
                else {
                        ans = s;
                }
        }

        if (ans.empty()) {
                cout << 0 << endl;
        }
        else {
                cout << ans << endl;
        }

        return true;
}
 

int main() {
        while (solve()) ;
}
accuracy: 1
time_ms: 300
memory_kb: 29820
final_rank: 8

code_snippet: // author: hanyu
#include <bits/stdc++.h>
using namespace std;

vector<int> di = {0, -1, -1, -1, 0, 1, 1, 1}, dj = {1, 1, 0, -1, -1, -1, 0, 1};

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);

  while (true) {
    int h, w;
    cin >> h >> w;
    if (h + w == 0) break;

    vector<string> x(h);
    for (int i = 0; i < h; i++) cin >> x[i];

    map<string, int> mp;
    for (int i = 0; i < h; i++) {
      for (int j = 0; j < w; j++) {
        for (int way = 0; way < 8; way++) {
          string s = "";
          int nowi = i, nowj = j;
          vector<vector<int>> visit(h, vector<int>(w, 0));
          while (true) {
            if (visit[nowi][nowj] == 1) break;
            visit[nowi][nowj] = 1;
            s += x[nowi][nowj];
            if (s.size() >= 2) mp[s]++;
            nowi += di[way];
            nowj += dj[way];
            if (nowi < 0) nowi += h;
            if (nowi >= h) nowi -= h;
            if (nowj < 0) nowj += w;
            if (nowj >= w) nowj -= w;
          }
        }
      }
    }

    string answer = "";
    for (auto i : mp) {
      if (i.second <= 1) continue;
      if (i.first.size() > answer.size()) answer = i.first;
    }

    if (answer == "") cout << 0 << endl;
    else cout << answer << endl;
  }
}
accuracy: 1
time_ms: 300
memory_kb: 29768
final_rank: 6

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pll;
typedef vector<ll> vll;
typedef vector<pll> vpll;
#define mp make_pair
#define pb push_back
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define rrep(i,l,r) for(int i=l;i<=r;i++)
#define chmin(a,b) a=min(a,b)
#define chmax(a,b) a=max(a,b)
#define all(x) x.begin(),x.end()
#define unq(x) sort(all(x));x.erase(unique(all(x)),x.end())
//#define mod 1000000007
#define mod 998244353
//ll mod;
#define ad(a,b) a=(a+b)%mod;
#define mul(a,b) a=a*b%mod;
void readv(vector<ll> &a,ll n){
	rep(i,n){
		ll x;
		cin>>x;
		a.push_back(x);
	}
}
void outv(vector<ll> &a,ll n){
	rep(i,n){
		if(i>0)cout<<" ";
		cout<<a[i];
	}
	cout<<"\n";
}
ll po(ll x,ll y){
	ll res=1;
	for(;y;y>>=1){
		if(y&1)res=res*x%mod;
		x=x*x%mod;
	}
	return res;
}
ll gcd(ll a,ll b){
	return (b?gcd(b,a%b):a);
}
#define FACMAX 200010
ll fac[FACMAX],inv[FACMAX],ivf[FACMAX];
void initfac(){
	fac[0]=ivf[0]=inv[1]=1;
	for(ll i=1;i<FACMAX;i++)fac[i]=fac[i-1]*i%mod;
	for(ll i=1;i<FACMAX;i++){
		if(i>1)inv[i]=(mod-mod/i*inv[mod%i]%mod)%mod;
		ivf[i]=po(fac[i],mod-2);
	}
}
ll P(ll n,ll k){
	if(n<0||n<k)return 0;
	return fac[n]*ivf[n-k]%mod;
}
ll C(ll n,ll k){
	if(k<0||n<k)return 0;
	return fac[n]*ivf[n-k]%mod*ivf[k]%mod;
}
ll H(ll n,ll k){
	return C(n+k-1,k);
}

ll dx[]={1,1,1,0,0,-1,-1,-1};
ll dy[]={1,0,-1,1,-1,1,0,-1};
ll h,w;
char c[10][20];
void solve(){
	vector<string> v;
	rep(i,h)rep(j,w){
		rep(dir,8){
			bool vis[10][20];
			rep(i,h)rep(j,w)vis[i][j]=0;
			string s;
			ll x=i,y=j;
			while(!vis[x][y]){
				vis[x][y]=1;
				s.pb(c[x][y]);
				v.pb(s);
				x=(x+dx[dir]+h)%h;
				y=(y+dy[dir]+w)%w;
			}
		}
	}
	sort(all(v));
	string res="0";
	rep(i,v.size()-1){
		if(v[i]==v[i+1]){
			bool ok=0;
			if(res.size()<v[i].size())ok=1;
			if(res.size()==v[i].size()&&res>v[i])ok=1;
			if(ok)res=v[i];
		}
	}
	cout<<res<<endl;
}
int main(){
	cin.tie(0);
	ios::sync_with_stdio(0);
	while(1){
		cin>>h>>w;
		if(h==0&&w==0)break;
		rep(i,h)rep(j,w)cin>>c[i][j];
		solve();
	}
}
accuracy: 1
time_ms: 230
memory_kb: 32580
final_rank: 17

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef long double ld;
typedef pair<ll, ll> pint;
#define rep(i, n) for(ll i = 0; i < (ll)n; i++)
#define ALL(v) (v).begin(), (v).end()
const ll MOD = 1000000007;
const ll INF = 1e16;
ll dx[8] = {-1, 0, 1, -1, 1, -1, 0, 1};
ll dy[8] = {-1, -1, -1, 0, 0, 1, 1, 1};

int main() {
  while(1) {
    ll H, W; cin >> H >> W;
    if(H == 0 && W == 0) break;
    vector<string> V(H);
    rep(i, H) cin >> V[i];
    map<string, ll> mp;
    rep(i, H) {
      rep(j, W) {
        rep(k, 8) {
          ll nx = j;
          ll ny = i;
          string S = "";
          S += V[ny][nx];
          while(1) {
            nx = (nx+dx[k]+W)%W;
            ny = (ny+dy[k]+H)%H;
            if(i == ny && j == nx) break;
            S += V[ny][nx];
            mp[S]++;
          }
        }
      }
    }
    vector<string> ans;
    ll sz = 0;
    for(auto c: mp) if(c.second > 1) sz = max(sz, (ll)c.first.size());
    for(auto c: mp) if(c.second > 1 && sz == (ll)c.first.size()) ans.push_back(c.first);
    if(ans.size() == 0) cout << 0 << "\n";
    else {
      
      sort(ALL(ans));
      cout << ans[0] << "\n";
    }
  }
}
accuracy: 1
time_ms: 380
memory_kb: 29996
final_rank: 12

code_snippet: #include<bits/stdc++.h>
using namespace std;

int main(){
	int h, w;
	while(cin >> h >> w){
		if(!h)return 0;
		vector<string> A(h);
		for(auto &&s:A)cin >> s;
		map<string,int> mp;
		auto safe=[&](int &y,int &x){
			if(y>=h)y-=h;
			if(x>=w)x-=w;
			if(y<0)y+=h;
			if(x<0)x+=w;
		};
		auto f=[&](int y,int x,int dy,int dx){
			string ans;
			ans+=A[y][x];
			int cy=y+dy,cx=x+dx;
			safe(cy,cx);
			while(cy!=y||cx!=x){
				ans+=A[cy][cx];
				cy+=dy,cx+=dx;
				safe(cy,cx);
                mp[ans]++;
			}
		};
		for(int y=0;y<h;y++){
			for(int x=0;x<w;x++){
				for(int dy=-1;dy<=1;dy++){
					for(int dx=-1;dx<=1;dx++){
						if(dy==0&&dx==0)continue;
						f(y,x,dy,dx);
					}
				}
			}
		}
		int maxv=0;
		string ans;
		for(auto p:mp){
            if(p.second==1)continue;
			if(p.first.size()>maxv){
				maxv=p.first.size();
				ans=p.first;
			}else if(p.first.size()==maxv){
				ans=min(ans,p.first);
			}
		}
        if(ans.empty())ans="0";
		cout << ans << '\n';
	}
}
accuracy: 1
time_ms: 300
memory_kb: 29972
final_rank: 9

code_snippet: #include <stdio.h>
#include <string>
#include <unordered_map>
using namespace std;

char pat[16][32], vis[16][32];
int dxy[8][2] = { {-1, 0}, {-1, 1}, {0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}, {-1, -1} };
unordered_map<string, int> u;

void clearmat(char* s, int h, int w, int ww) {
    for (int i = 0; i < h; i++) {
        for (int j = 0; j < w; j++) s[i * ww + j] = 0;
    }
}

int main(void) {
    int h, w, x, y;
    string s;
    while (1) {
        scanf("%d %d", &h, &w);
        if (h == 0) break;
        for (int i = 0; i < h; i++) {
            scanf("%s", pat[i]);
        }
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                for (int d = 0; d < 8; d++) {
                    x = i, y = j;
                    s = "";
                    while (!vis[x][y]) {
                        vis[x][y] = 1;
                        s += pat[x][y];
                        if (s.length() > 1) {
                            if (u.find(s) == u.end()) u.insert(pair<string, int>(s, 1));
                            else u[s]++;
                        }
                        x += dxy[d][0];
                        y += dxy[d][1];
                        if (x < 0) x += h;
                        if (x >= h) x -= h;
                        if (y < 0) y += w;
                        if (y >= w) y -= w;
                    }
                    clearmat((char*)vis, h, w, 32);
                }
            }
        }

        s = "";
        for (auto i : u) {
            if (i.second > 1) {
                if (i.first.length() > s.length()) s = i.first;
                else if (i.first.length() == s.length() && s.compare(i.first) > 0) s = i.first;
            }
        }
        u.clear();
        if (s.length() < 2) printf("0\n");
        else printf("%s\n", s.c_str());
    }
    return 0;
}
accuracy: 1
time_ms: 300
memory_kb: 28644
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long;
#define rep(i, n) for (int i = 0; i < (n); i++)
#define ALL(x) x.begin(), x.end()

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;
    while (cin >> H >> W) {
        if (H == 0 && W == 0) break;
        vector<string> G(H);
        rep(i, H) cin >> G[i];
        string ans = "";
        rep(x1, H) rep(y1, W) rep(x2, H) rep(y2, W) {
            if (G[x1][y1] != G[x2][y2]) continue;
            rep(k1, 8) rep(k2, 8) {
                if (x1 == x2 && y1 == y2 && k1 == k2) continue;
                int nx1 = (x1 + dx[k1] + H) % H, ny1 = (y1 + dy[k1] + W) % W;
                int nx2 = (x2 + dx[k2] + H) % H, ny2 = (y2 + dy[k2] + W) % W;
                if (G[nx1][ny1] != G[nx2][ny2]) continue;
                string s = "";
                s += G[x1][y1];
                vector<vector<int>> seen1(H, vector<int>(W)), seen2(H, vector<int>(W));
                seen1[x1][y1] = 1;
                seen2[x2][y2] = 1;
                while (G[nx1][ny1] == G[nx2][ny2] && seen1[nx1][ny1] == 0 && seen2[nx2][ny2] == 0) {
                    s += G[nx1][ny1];
                    seen1[nx1][ny1] = 1;
                    seen2[nx2][ny2] = 1;
                    nx1 = (nx1 + dx[k1] + H) % H, ny1 = (ny1 + dy[k1] + W) % W;
                    nx2 = (nx2 + dx[k2] + H) % H, ny2 = (ny2 + dy[k2] + W) % W;
                }
                if (ans.size() == 0)
                    ans = s;
                else if (ans.size() < s.size() || (ans.size() == s.size() && ans > s))
                    ans = s;
            }
        }
        if (ans.size() == 0)
            cout << 0 << '\n';
        else
            cout << ans << '\n';
    }
    return 0;
}
accuracy: 1
time_ms: 2450
memory_kb: 3372
final_rank: 13

code_snippet: #include <bits/stdc++.h>
#define rep(i, a, n) for(int i = a; i < (n); i++)
using namespace std;
using ll = long long;
using P = pair<int, int>;
const int INF = 1001001001;
const ll LINF = 1001002003004005006ll;
//const int mod = 1000000007;
//const int mod = 998244353;
const int di[] = {1,1,0,-1,-1,-1,0,1};
const int dj[] = {0,1,1,1,0,-1,-1,-1};

int main()
{
    while(true){
        int h, w;
        cin >> h >> w;
        if(h == 0 && w == 0) return 0;
        vector<string> s(h);
        rep(i, 0, h) cin >> s[i];
        map<string, int> mp;
        string ans;
        auto dfs = [&](auto& f, int si, int sj, int i, int j, int dir, string t) -> void{
            int ni = (i + di[dir] + h)%h;
            int nj = (j + dj[dir] + w)%w;
            mp[t]++;
            if(si == ni && sj == nj) return;
            else f(f, si, sj, ni, nj, dir, t + s[ni][nj]);
        };
        rep(i, 0, h){
            rep(j, 0, w){
                rep(dir, 0, 8){
                    string t;
                    t += s[i][j];
                    dfs(dfs, i, j, i, j, dir, t);
                }
            }
        }
        for(auto i : mp){
            if(i.second >= 2){
                if(ans.size() == i.first.size()) ans = min(ans, i.first);
                else ans = (ans.size() > i.first.size()) ? ans : i.first;
            }
        }
        if(ans.size() <= 1) cout << 0 << endl;
        else cout << ans << endl;
    }
}
accuracy: 1
time_ms: 380
memory_kb: 30216
final_rank: 15

code_snippet: // #include "atcoder/all"
#include <iostream> // cout, endl, cin
#include <string> // string, to_string, stoi
#include <vector> // vector
#include <algorithm> // min, max, swap, sort, reverse, lower_bound, upper_bound
#include <utility> // pair, make_pair
#include <tuple> // tuple, make_tuple
#include <cstdint> // int64_t, int*_t
#include <cstdio> // printf
#include <map> // map
#include <queue> // queue, priority_queue
#include <set> // set
#include <stack> // stack
#include <deque> // deque
#include <unordered_map> // unordered_map
#include <unordered_set> // unordered_set
#include <bitset> // bitset
#include <cctype> // isupper, islower, isdigit, toupper, tolower
#include <iomanip> // setprecision
#include <complex> // complex
#include <math.h>
#include <functional>
#include <cassert>
using namespace std;
// using namespace atcoder;
using ll = long long;
using P = pair<ll,ll>;
constexpr ll INF = 1e18;
constexpr ll LLMAX = 9223372036854775807;
constexpr int inf = 1e9;
constexpr ll mod = 1000000007;
// constexpr ll mod = 998244353;
// 右下左上
const int dx[8] = {1, 0, -1, 0,1,1,-1,-1};
const int dy[8] = {0, 1, 0, -1,1,-1,1,-1};
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
#define eol endl
// ---------------------------------------------------------------------------

bool solve(){
  int H,W;
  cin >> H >> W;
  if(H == 0) return false;
  vector<string> G(H);
  for(int i=0; i<H; i++){
    cin >> G[i];
  }
  set<string> mp;
  int ansL = 0;
  string ansS = "";
  for(int i=0; i<H; i++){
    for(int j=0; j<W; j++){
      for(int k=0; k<8; k++){
        int y = i;
        int x = j;
        string now = "";
        now += G[y][x];
        y += dy[k];
        x += dx[k];
        y += H;
        x += W;
        y %= H;
        x %= W;
        while(y != i || x != j){
          now += G[y][x];
          if(mp.count(now)){
            if(ansL < now.size()){
              ansL = now.size();
              ansS = now;
            }else if(ansL == now.size()){
              chmin(ansS,now);
            }
          }else{
            mp.emplace(now);
          }
          y += dy[k];
          x += dx[k];
          y += H;
          x += W;
          y %= H;
          x %= W;
        }
      }
    }
  }
  if(ansL <= 1){
    cout << 0 << endl;
  }else{
    cout << ansS << endl;
  }
  return true;
}

int main(){
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  while(solve());
  return 0;
}
accuracy: 1
time_ms: 300
memory_kb: 29788
final_rank: 7

code_snippet: #include<bits/stdc++.h>
using namespace std;

using ll = long long;
const int INF = 1e9;
const ll inf = 1LL<<60;

vector<int> dx = {0, 1, 1, 1, 0, -1, -1, -1};
vector<int> dy = {1, 1, 0, -1, -1, -1, 0, 1};

bool solve() {
  int h, w; cin >> h >> w;
  if (h == 0) return false;
  vector<string> s(h);
  for (int i=0; i<h; i++) cin >> s[i];
  vector<string> S;
  for (int i=0; i<h; i++) for (int j=0; j<w; j++) {
    for (int k=0; k<8; k++) {
      string t = "";
      t += s[i][j];
      int nx = i, ny = j;
      while (1) {
        nx = (nx + dx[k]);
        ny = (ny + dy[k]);
        if (nx < 0) nx = h-1;
        if (ny < 0) ny = w-1;
        if (nx >= h) nx = 0;
        if (ny >= w) ny = 0;
        if (i == nx && j == ny) break;
        t += s[nx][ny];
      }
      if (t.size() == 1) continue;
      S.push_back(t);
    }
  }
  auto calc = [](string &a, string &b) -> string {
    string res = "";
    for (int i=0; i<min(a.size(), b.size()); i++) {
      if (a[i] != b[i]) break;
      res += a[i];
    }
    return res;
  };
  int ma = 2;
  set<string> P;
  for (int i=0; i<S.size(); i++) for (int j=i+1; j<S.size(); j++) {
    string k = calc(S[i], S[j]);
    if (k.size() < ma) continue;
    P.insert(k);
    ma = max(ma, (int)k.size());
  }
  for (auto c : P) if (c.size() == ma) {
    cout << c << endl;
    return true;
  }
  cout << 0 << endl;
  return true;
}

int main() {
  while (solve());
}
accuracy: 1
time_ms: 180
memory_kb: 3592
final_rank: 1

code_snippet: #include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <utility>
#include <map>

using namespace std;

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

int main() {
	int h, w;
	while (cin >> h >> w, h || w) {
		vector<string> vs(h);
		for (auto& s : vs) cin >> s;
		vector<map<string, int> > mps(h * w + 1);
		int ans_len = 0;
		for (int x = 0; x < h; ++x) {
			for (int y = 0; y < w; ++y) {
				for (int i = 0; i < 9; ++i) {
					string tmp { vs[x][y] };
					int nx = x, ny = y;
					while (true) {
						nx = (nx + dx[i] + h) % h;
						ny = (ny + dy[i] + w) % w;
						if (x == nx && y == ny) break;
						tmp += vs[nx][ny];
						++mps[tmp.length()][tmp];
						if (mps[tmp.length()][tmp] > 1)
							ans_len = max(ans_len, (int)tmp.length());
					}
				}
			}
		}
		if (ans_len) {
			string ans(ans_len, 'Z');
			for (auto& [s, count] : mps[ans_len])
				if (count > 1 && ans > s) ans = s;
			cout << ans << endl;
		} else cout << 0 << endl;
	}

	return 0;
}
accuracy: 1
time_ms: 220
memory_kb: 29704
final_rank: 3

code_snippet: #include <bits/stdc++.h>
#define rep(i,n) for(int i = 0; i < (n); i++)
using namespace std;
typedef long long ll;

int main(){
	cin.tie(0);
	ios::sync_with_stdio(0);

	int di[] = {-1, -1, -1,  0,  0, +1, +1, +1};
	int dj[] = {-1,  0, +1, -1, +1, -1,  0, +1};
	
	while(true) {
		int h,w; cin >> h >> w; if(h == 0) break;
		vector< string > s(h);
		rep(i,h) cin >> s[i];

		map<string,int> mp;
		rep(d,8) {
			vector<vector<bool>> used(h, vector<bool> (w, false));
			rep(i,h)rep(j,w) {
				if(used[i][j]) continue;
				int ci = i, cj = j;
				string t = "";
				while(!used[ci][cj]) {
					used[ci][cj] = true;
					t += s[ci][cj];
					ci = (ci + di[d] + h) % h;
					cj = (cj + dj[d] + w) % w;
				}
				
				int N = t.size();
				t += t;
				rep(k,N)for(int c = 2; c <= N; c++)
					mp[t.substr(k, c)]++;
			}
		}

		string ans = "";
		for(auto e : mp) if(e.second >= 2) {
			string t = e.first;
			if(t.size() > ans.size()) ans = t;
			else if(t.size() == ans.size()) ans = min(ans, t);
		}
		cout << (ans.size() == 0 ? "0" : ans) << endl;
	}
}
accuracy: 1
time_ms: 320
memory_kb: 29936
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define all(A) A.begin(),A.end()
using vll = vector<ll>;
#define rep(i, n) for (long long i = 0; i < (long long)(n); i++)


vll dx = { 1,-1,0 };
vll dy = { 1,-1,0 };
int main() {
    while (1) {
        ll H, W;
        cin >> H >> W;
        if (H == 0)return 0;
        vector<vector<char>> V(H, vector<char>(W));
        rep(h, H) {
            string S;
            cin >> S;
            rep(w, W)V[h][w] = S[w];
        }
        map<string, ll> M;
        rep(h, H) {
            rep(w, W) {
                rep(i, 8) {
                    ll x = h; ll y = w;
                    string K = "";
                    while (1) {
                        K += V[x][y];
                        x += dx[i / 3]+H;
                        y += dy[i % 3]+W;
                        x %= H; y %= W;
                        M[K]++;
                        if (x == h && y == w) {
                            
                            break;
                        }
                    }
                }
            }
        }
        ll m = 0;
        string an = "0";
        for (auto p : M) {
            if (p.second > 1) {
                if (p.first.size() > an.size()) {
                    an = p.first;
                }
                else if (p.first.size() == an.size()) {
                    if (p.first < an) {
                        an = p.first;
                    }
                }
            }
        }
        cout << an << endl;
    }
}
accuracy: 1
time_ms: 310
memory_kb: 30056
final_rank: 10

code_snippet: #pragma region Macros
#include <bits/stdc++.h>
using namespace std;
template <class T> inline bool chmax(T &a, T b) {
    if(a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <class T> inline bool chmin(T &a, T b) {
    if(a > b) {
        a = b;
        return 1;
    }
    return 0;
}
#ifdef DEBUG
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    os << '{';
    for(int i = 0; i < (int)v.size(); i++) {
        if(i) { os << ','; }
        os << v[i];
    }
    os << '}';
    return os;
}
void debugg() { cerr << endl; }
template <class T, class... Args>
void debugg(const T &x, const Args &... args) {
    cerr << " " << x;
    debugg(args...);
}
#define debug(...)                                                             \
    cerr << __LINE__ << " [" << #__VA_ARGS__ << "]: ", debugg(__VA_ARGS__)
#define dump(x) cerr << __LINE__ << " " << #x << " = " << (x) << endl
#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif

struct Setup {
    Setup() {
        cin.tie(0);
        ios::sync_with_stdio(false);
        cout << fixed << setprecision(15);
    }
} __Setup;

using ll = long long;
#define ALL(v) (v).begin(), (v).end()
#define RALL(v) (v).rbegin(), (v).rend()
#define FOR(i, a, b) for(int i = (a); i < int(b); i++)
#define REP(i, n) FOR(i, 0, n)
const int INF = 1 << 30;
const ll LLINF = 1LL << 60;
constexpr int MOD = 1000000007;

void Case(int i) { cout << "Case #" << i << ": "; }
int popcount(int x) { return __builtin_popcount(x); }
ll popcount(ll x) { return __builtin_popcountll(x); }
#pragma endregion Macros

const int di[8] = {-1, -1, 0, 1, 1, 1, 0, -1};
const int dj[8] = {0, 1, 1, 1, 0, -1, -1, -1};

bool solve() {
    int N, M;
    cin >> N >> M;
    if(N == 0) return false;
    vector<string> G(N);
    REP(i, N) cin >> G[i];

    map<string, int> cnt;
    REP(si, N) REP(sj, M) {
        set<string> se;
        REP(dir, 8) {
            string s = "";
            int ni = si, nj = sj;
            while(1) {
                s += G[ni][nj];
                se.emplace(s);
                ni = (ni + di[dir] + N) % N;
                nj = (nj + dj[dir] + M) % M;
                if(ni == si and nj == sj) break;
            }
        }
        for(auto s : se) cnt[s] += 1;
    }
    string ans = "";
    for(const auto& [s, num] : cnt) {
        if(num <= 1) continue;
        if(ans.size() < s.size()) ans = s;
        else if(ans > s) ans = s;
    }

    if((int)ans.size() <= 1) cout << "0\n";
    else cout << ans << "\n";
    return true;
}

int main() {
    while(solve());
}
accuracy: 1
time_ms: 490
memory_kb: 30216
final_rank: 20

code_snippet: #include<bits/stdc++.h>
using namespace std;
using P = pair<int,int>;

void solve(int H, int W){
  vector<string> vec(H);
  for(int i=0; i<H; i++){
    cin >> vec[i];
  }
  set<string> S;
  string ans = "";
  for(int i=0; i<H; i++){
    for(int j=0; j<W; j++){
      for(int a=-1; a<=1; a++){
        for(int b=-1; b<=1; b++){
          if(a == 0 && b == 0){
            continue;
          }
          string add = "";
          set<P> p;
          int x = i;
          int y = j;
          while(true){
            if(p.count(P(x,y))){
              break;
            }
            add += vec[x][y];
            p.insert(P(x,y));
            x = (x+a+H)%H;
            y = (y+b+W)%W; 
            if(S.count(add)){
              if(add.size() > ans.size()){
                ans = add;
              }
              if(add.size() == ans.size() && add < ans){
                ans = add;
              }
            }
            S.insert(add);
          }
        }
      }
    }
  }
  if(ans.size() <= 1){
    cout << 0 << endl;
  }
  else{
    cout << ans << endl;
  }
}

int main(){
  while(true){
    int H, W;
    cin >> H >> W;
    if(H == 0){
      break;
    }
    solve(H,W);
  }
}
accuracy: 1
time_ms: 480
memory_kb: 29904
final_rank: 18