#pragma region header #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; struct Init{Init(){std::cin.tie(0); ios::sync_with_stdio(false); cout << setprecision(20) << fixed;}} init; using ll = long long; using ull = unsigned long long; using ld = long double; #define all(x) begin((x)), end((x)) #define pb push_back #define mp make_pair #define mt make_tuple #define uq(v) v.erase(unique(begin(v), end(v)), end(v)) template using pq = priority_queue; template using pq_g = priority_queue, greater>; template bool chmax(T &a, const T &b){if(a < b){a = b; return 1; } return 0;} template bool chmin(T &a, const T &b){if(a > b){a = b; return 1; } return 0;} constexpr ll INF = 2e18; constexpr int inf = 1e9; constexpr ld eps = 1e-15; constexpr int dx[8] = {1, 0, -1, 0, 1, 1, -1, -1}; constexpr int dy[8] = {0, 1 ,0, -1, 1, -1, 1, -1}; #pragma endregion header template struct MontgomeryModInt { private: using mint = MontgomeryModInt; using i32 = int32_t; using i64 = int64_t; using u32 = uint32_t; using u64 = uint64_t; static constexpr u32 get_r() { u32 ret = mod_; for (i32 i = 0; i < 4; i++) ret *= 2 - mod_ * ret; return ret; } static constexpr u32 r = get_r(); static constexpr u32 n2 = -u64(mod_) % mod_; static_assert(r * mod_ == 1, "invalid, r * mod != 1"); static_assert(mod_ < (1 << 30), "invalid, mod >= 2 ^ 30"); static_assert((mod_ & 1) == 1, "invalid, mod % 2 == 0"); u32 x; public: MontgomeryModInt() : x{} {} MontgomeryModInt(const i64 &a): x(reduce(u64(fast ? a : (a % mod() + mod())) * n2)) {} static constexpr u32 reduce(const u64 &b) { return u32(b >> 32) + mod() - u32((u64(u32(b) * r) * mod()) >> 32); } mint &operator+=(const mint &p) { if (i32(x += p.x - 2 * mod()) < 0) x += 2 * mod(); return *this; } mint &operator-=(const mint &p) { if (i32(x -= p.x) < 0) x += 2 * mod(); return *this; } mint &operator*=(const mint &p) { x = reduce(u64(x) * p.x); return *this; } mint &operator/=(const mint &p) { *this *= p.inv(); return *this; } mint operator-() const { return mint() - *this; } mint operator+(const mint &p) const { return mint(*this) += p; } mint operator-(const mint &p) const { return mint(*this) -= p; } mint operator*(const mint &p) const { return mint(*this) *= p; } mint operator/(const mint &p) const { return mint(*this) /= p; } bool operator==(const mint &p) const { return (x >= mod() ? x - mod() : x) == (p.x >= mod() ? p.x - mod() : p.x); } bool operator!=(const mint &p) const { return (x >= mod() ? x - mod() : x) != (p.x >= mod() ? p.x - mod() : p.x); } u32 val() const { u32 ret = reduce(x); return ret >= mod() ? ret - mod() : ret; } mint pow(u64 n) const { mint ret(1), mul(*this); while (n > 0) { if (n & 1) ret *= mul; mul *= mul; n >>= 1; } return ret; } mint inv() const { return pow(mod() - 2); } friend ostream &operator<<(ostream &os, const mint &p) { return os << p.val(); } friend istream &operator>>(istream &is, mint &a) { i64 t; is >> t; a = mint(t); return is; } static constexpr u32 mod() { return mod_; } }; template using modint = MontgomeryModInt; using mint = modint<998244353>; using modint1000000007 = modint<1000000007>; int main(){ int N, M; cin >> N >> M; string S; cin >> S; vector> H(N); for(int i = 0; i < M; ++i){ int A, B; cin >> A >> B; H[--A].pb(--B); H[B].pb(A); } int cnt = 0; for(int i = 0; i < N; ++i) if(S[i] == '?') ++cnt; mint tei = 1; for(int i = 0; i < cnt; ++i) tei *= 26; mint ans = 0; for(int i = 0; i < N; ++i){ int num = 0; if(S[i] == '?') ++num; else if(S[i] != 'a') continue; for(auto u: H[i]){ if(S[u] == '?') ++num; else if(S[u] != 'o') continue; for(auto v: H[u]){ if(S[v] == '?') ++num; else if(S[v] != 'i') continue; if(v == i){ if(S[v] == '?') --num; continue; } if(num == 0) ans += tei; if(num == 1) ans += tei / 26; if(num == 2) ans += tei / (26 * 26); if(num == 3) ans += tei / (26 * 26 * 26); if(S[v] == '?') --num; } if(S[u] == '?') --num; } } cout << ans << "\n"; }