#include [[nodiscard]] static inline constexpr std::array count([[maybe_unused]] const uint_fast32_t N, const uint_fast32_t i, const std::vector& S) noexcept { std::array count_of = { 0, 0, 0 }; for (const auto& s : S) if (!s.empty()) { [[assume(i < s.size())]]; switch (s[i]) { case 'G': ++count_of[0]; break; case 'C': ++count_of[1]; break; case 'P': ++count_of[2]; break; default: [[unlikely]] break; } } return count_of; } [[nodiscard]] static inline constexpr char decide(const std::array& count_of) noexcept { if (count_of[0] == 0) { if (count_of[2] == 0) return 'G'; else return 'C'; } else if (count_of[1] == 0) { if (count_of[0] == 0) return 'C'; else return 'P'; } else if (count_of[2] == 0) { if (count_of[1] == 0) return 'P'; else return 'G'; } return 0; } [[nodiscard]] static inline constexpr bool check(const std::vector& S) noexcept { for (const auto& s : S) if (!s.empty()) return false; return true; } [[nodiscard]] static inline constexpr std::string solve(const uint_fast32_t N, const uint_fast32_t M, std::vector& S) noexcept { std::string ans(M, 0); for (uint_fast32_t i = 0; i != M; ++i) { const std::array& count_of = count(N, i, S); if ((ans[i] = decide(count_of)) == 0) return "-1"; for (auto& s : S) if (!s.empty() && s[i] != ans[i]) s.clear(); } if (check(S)) return ans; else return "-1"; } int main() { std::cin.tie(nullptr); std::ios::sync_with_stdio(false); uint_fast32_t N, M; std::cin >> N >> M; std::vector S(N); for (auto& s : S) s.reserve(M), std::cin >> s; std::cout << solve(N, M, S) << '\n'; return 0; }