#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; // BEGIN NO SAD #define rep(i, a, b) for(int i = a; i < (b); ++i) #define trav(a, x) for(auto& a : x) #define all(x) x.begin(), x.end() #define sz(x) (int)(x).size() #define mp make_pair #define pb push_back #define eb emplace_back #define lb lower_bound #define ub upper_bound typedef vector vi; #define f first #define s second #define derr if(1) cerr // END NO SAD template class y_combinator_result { Fun fun_; public: template explicit y_combinator_result(T &&fun): fun_(std::forward(fun)) {} template decltype(auto) operator()(Args &&...args) { return fun_(std::ref(*this), std::forward(args)...); } }; template decltype(auto) y_combinator(Fun &&fun) { return y_combinator_result>(std::forward(fun)); } template bool updmin(T& a, T b) { if(b < a) { a = b; return true; } return false; } template bool updmax(T& a, T b) { if(b > a) { a = b; return true; } return false; } typedef long long ll; typedef pair pii; typedef pair pll; typedef vector> matrix; void die() { cout << "-1\n"; exit(0); } void solve() { int n, k; cin >> n >> k; vector g(n); vector> poss(k); for(int i = 0; i < n; i++) { cin >> g[i]; for(int j = 0; j < k; j++) { if(g[i][j] != 'X') poss[j].pb(i); } } vector correct(n); string ret = ""; auto dfs = y_combinator([&](auto self) -> bool { if(sz(ret) == k) return true; for(auto want: "FT") { if(!want) continue; bool can = true; for(auto out: poss[sz(ret)]) { if(g[out][sz(ret)] == want) { if(++correct[out] > 1) can = false; } } ret += want; if(can && self()) return true; ret.pop_back(); for(auto out: poss[sz(ret)]) correct[out] -= g[out][sz(ret)] == want; } return false; }); if(!dfs()) ret = "-1"; else assert(sz(ret) == k); cout << ret << "\n"; } int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); solve(); }