#include #include #include #include #include #include #include #include #include #include #include #include using namespace atcoder; using namespace std; #define rep(i, n) for (int i = 0; i < (n); ++i) #define Yes cout << "Yes" << endl #define No cout << "No" << endl #define vl vector #define vvl vector> #define vvvl vector>> #define vc vector #define vvc vector> #define vb vector #define vvb vector> #define nall(a) a.begin(), a.end() #define rall(a) a.rbegin(), a.rend() #define chmax(x, y) x = max(x, y) #define chmin(x, y) x = min(x, y) #define yu_qgrid(x, y) ((x) * (x) + (y) * (y)) // ユークリッド距離 (sqrtはしない) #define mannhattan(x1, x2, y1, y2) abs(x1 - x2) + abs(y1 - y2) #define PI 3.14159265359 using ll = long long; //using mint = modint1000000007; using mint = modint998244353; using P = pair; vl di = {1, 0, -1, 0}; // 下、左、上、右 vl dj = {0, -1, 0, 1}; bool out_grid(ll i, ll j, ll h, ll w) { return !(0 <= i && i < h && 0 <= j && j < w); } ll INF = 1e18; int main(){ ll n,m; cin >> n >> m; string s; cin >> s; vvl g(n); rep(i,m){ ll a,b; cin >> a >> b; a--;b--; g[a].push_back(b); g[b].push_back(a); } ll count_hatena = 0; rep(i,n){ if(s[i] == '?') count_hatena++; } mint ans = 0; map mp; mp['a'] = 'o'; mp['o'] = 'i'; auto dfs = [&](auto dfs,char pre,ll hatena,ll v,vb seen) -> void{ char nex = mp[pre]; for(ll u : g[v]){ if(seen[u])continue; if(pre == 'o'){ ll e = INF; if(s[u] == nex){ e = count_hatena-hatena; } if(s[u] == '?'){ e = count_hatena-hatena-1; } if(e == INF)continue; if(e == 0){ ans += 1; } else{ mint base = 26; base.pow(e); ans += base; } } else{ seen[u] = true; if(s[u] == '?'){ dfs(dfs,nex,hatena+1,u,seen); } if(s[u] == nex){ dfs(dfs,nex,hatena,u,seen); } seen[u] = false; } } return; }; for(int v = 0;v < n;v++){ vb seen(n); seen[v] = true; if(s[v] != 'a' && s[v] != '?')continue; if(s[v] == 'a'){ dfs(dfs,'a',0,v,seen); } else{ dfs(dfs,'a',1,v,seen); } } cout << ans.val() << endl; }