Problem:
H: TUAT文字列
問題
農工大文字列部の部員たちは長さ \(N\) の文字列の中から「TUAT文字列」を探そうとしています。
TUAT文字列は、以下の条件を満たす文字列です。
文字列は英子文字からなる。
母音字を
a
,
e
,
i
,
o
,
u
として、子音字をそれ以外の英子文字とする。
ある子音字 \(p\)、相異なる母音字 \(q, r\) を用いて、
        それぞれ長さが \(1\) 以上からなる \(pp...p, qq...q, rr...r, pp...p\) をこの順に連結した文字列
例えば、「
tuat
」や「
beeeabbb
」はTUAT文字列ですが、
    「
saas
」や「
yeeaaahh
」は「同じ母音を使っている」、「異なる子音を使っている」
    という理由でTUAT文字列ではありません。
部員たちは手分けしてTUAT文字列を探そうとしています。
あなたは、辞書順で \(S\) と同じかそれより大きいかつ、
    \(T\) と同じかそれより小さい文字列に含まれるTUAT文字列を探します。
そのような条件を満たすTUAT文字列の個数を \(998244353\) で割った余りを答えてください。
入力形式
N
S
T
制約
\(4 \leq N \leq 10^4\)
\(|S| = |T| = N\)
\(S, T\) は英小文字からなる文字列
出力形式
条件を満たすTUAT文字列の個数を \(998244353\) で割った余りを出力せよ。
入力例1
4
tuat
tuee
出力例1
1
tuat
のみが条件を満たします。
入力例2
11
qlethonyori
totorinyaaa
出力例2
7336
入力例3
41
electricalengineeringandcomputerscienceof
tokyouniversityofagricultureandtechnology
出力例3
2380206

Submitted solutions:

code_snippet: // AOJ #3236
// TUAT String 2025.2.13

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll MOD = 998244353;
 
string decString(const string &s) {
    string t = s;
    int n = t.size();
    int i = n - 1;
    while(i >= 0 && t[i] == 'a') i--;
    if(i < 0) return "";
    t[i] = char(t[i] - 1);
    for(int j = i+1; j < n; j++) t[j] = 'z';
    return t;
}
 
 
ll solveForPattern(const string &U, const char pat[4]) {
    int n = U.size();
    vector<vector<int>> nt(n, vector<int>(26,0));
    for (int pos = 0; pos < n; pos++){
        int bound = U[pos] - 'a';
        for (int c = 0; c < 26; c++){
            if(c < bound) nt[pos][c] = 0;
            else if(c == bound) nt[pos][c] = 1;
            else nt[pos][c] = -1;
        }
    }
 
    ll dp[16] = {0}, ndp[16] = {0};
    dp[1] = 1;
 
    for (int pos = 0; pos < n; pos++){
        for(int i=0; i<16; i++) ndp[i] = 0;
        for (int s = 0; s < 16; s++){
            ll ways = dp[s];
            if(!ways) continue;
            int seg = s >> 2;
            int started = (s >> 1) & 1;
            int t = s & 1;
            int li = pat[seg] - 'a';
            int new_t;
            if(t == 1){
                new_t = nt[pos][li];
                if(new_t != -1){
                    int ns = (seg << 2) | (1 << 1) | new_t;
                    ndp[ns] = (ndp[ns] + ways) % MOD;
                }
            } else {
                new_t = 0;
                int ns = (seg << 2) | (1 << 1) | new_t;
                ndp[ns] = (ndp[ns] + ways) % MOD;
            }
            if(started==1 && seg < 3){
                int li2 = pat[seg+1] - 'a';
                int new_t2;
                if(t == 1){
                    new_t2 = nt[pos][li2];
                    if(new_t2 != -1){
                        int ns = ((seg+1) << 2) | (1 << 1) | new_t2;
                        ndp[ns] = (ndp[ns] + ways) % MOD;
                    }
                } else {
                    new_t2 = 0;
                    int ns = ((seg+1) << 2) | (1 << 1) | new_t2;
                    ndp[ns] = (ndp[ns] + ways) % MOD;
                }
            }
        }
        for(int i = 0; i < 16; i++) dp[i] = ndp[i];
    }
    ll res = 0;
    for (int s = 0; s < 16; s++){
        int seg = s >> 2;
        int started = (s >> 1) & 1;
        if(seg==3 && started==1) res = (res + dp[s]) % MOD;
    }
    return res;
}
 
 
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
 
    int N;
    cin >> N;
    string S, T;
    cin >> S >> T;
 
    string Sminus = decString(S);
 
    vector<char> vowels = {'a','e','i','o','u'};
    vector<char> cons;
    for(char c = 'a'; c <= 'z'; c++){
        if(c=='a' || c=='e' || c=='i' || c=='o' || c=='u') continue;
        cons.push_back(c);
    }
 
    ll ans = 0;
    char pat[4];
    for(auto p : cons){
        for(auto q : vowels){
            for(auto r : vowels){
                if(q == r) continue;
                pat[0] = p;
                pat[1] = q;
                pat[2] = r;
                pat[3] = p;
                ll waysT = solveForPattern(T, pat);
                ll waysS = 0;
                if(!Sminus.empty())
                    waysS = solveForPattern(Sminus, pat);
                ll cnt = (waysT - waysS + MOD) % MOD;
                ans = (ans + cnt) % MOD;
            }
        }
    }
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 740
memory_kb: 4436
final_rank: 17

code_snippet: #include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <set>
#include <vector>
#include <numeric>
#include <algorithm>
#include <queue>
#include <string>
#include <random>
#include <array>
#include <climits>
#include <map>
#include <cassert>
#include <stack>
#include <iomanip>
#include <cfloat>
#include <bitset>
#include <fstream>
#include <chrono>

constexpr int MOD = 998244353;
long long int count_under(const char p, const char q, const char r, const std::string& str) {
	if (str[0] < p) return 0;
	const int n = str.size();
	std::vector<long long int> just(4, 0), under(4, 0);
	if (str[0] == p) {
		just[0] = 1;
	}
	else {
		under[0] = 1;
	}
	const std::array<char, 4> chars{ p, q, r, p };
	for (auto i = 1; i < n; ++i) {
		std::vector<long long int> next_just(4, 0), next_under(4, 0);
		for (auto j = 0; j < 4; ++j) {
			const auto c = chars[j];
			if (c < str[i]) {
				next_under[j] += just[j];
				if (j > 0) {
					next_under[j] += just[j - 1];
				}
			}
			else if (c == str[i]) {
				next_just[j] += just[j];
				if (j > 0) {
					next_just[j] += just[j - 1];
				}
			}
			next_under[j] += under[j];
			if (j > 0) {
				next_under[j] += under[j - 1];
			}
			next_just[j] %= MOD;
			next_under[j] %= MOD;
		}
		std::swap(just, next_just);
		std::swap(under, next_under);
	}
	return (just[3] + under[3]) % MOD;
}
bool is_tuat(std::string str) {
	const std::string boin = "aiueo";
	const std::string shiin = "bcdfghjklmnpqrstvwxyz";
	str.erase(std::unique(str.begin(), str.end()), str.end());
	if (str.size() != 4) return false;
	if (str[0] != str[3]) return false;
	if (str[1] == str[2]) return false;
	if (shiin.find(str[0]) == std::string::npos) return false;
	if (boin.find(str[1]) == std::string::npos) return false;
	if (boin.find(str[2]) == std::string::npos) return false;
	return true;
}
int main() {
	const std::string boin = "aiueo";
	const std::string shiin = "bcdfghjklmnpqrstvwxyz";
	int n; std::cin >> n;
	std::string from, to; std::cin >> from >> to;
	long long int diff{ 0 };
	for (const auto p : shiin) {
		for (const auto q : boin) {
			for (const auto r : boin) {
				if (q == r) continue;
				const auto under_from = count_under(p, q, r, from);
				const auto under_to = count_under(p, q, r, to);
				diff += under_to - under_from;
			}
		}
	}
	if (is_tuat(from)) ++diff;
	diff = (diff % MOD + MOD) % MOD;
	std::cout << diff << '\n';
}
accuracy: 1
time_ms: 240
memory_kb: 3476
final_rank: 7

code_snippet: #include <bits/stdc++.h>
//#include<atcoder/all>
using namespace std;
//using namespace atcoder;
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++)

ll mod = 1e9 + 7;


int main() {
	ll N;
	cin >> N;
	string S, T;
	cin >> S >> T;
	ll mod = 998244353;
	ll an = 0;
	string siin = "qwrtypsdfghjklzxcvbnm";
	string boin = "aiueo";
	rep(s, 21) {//1,4文字目
		char P = siin[s];
		rep(b, 5) {//2文字目
			char B = boin[b];
			rep(c, 5) {//3文字目
				char C = boin[c];
				if (P == 'w' && B == 'a' && C == 'i') {
					cout << "";
				}
				if (b == c)continue;
				vector<vll> DPSJ(N + 1, vll(5, 0));
				vector<vll> DPTJ(N + 1, vll(5, 0));
				vector<vll> DPT(N + 1, vll(5, 0));
				vector<vll> DPS(N + 1, vll(5, 0));
				DPTJ[0][0] = 1;
				DPSJ[0][0] = 1;
				rep(i, N) {
					DPT[i + 1][1] += DPT[i][1] + DPT[i][0];
					DPS[i + 1][4] += DPS[i][4] + DPS[i][3];
					DPT[i + 1][4] += DPT[i][4] + DPT[i][3];
					DPS[i + 1][1] += DPS[i][1] + DPS[i][0];
					if (S[i] < P) {
						DPS[i + 1][1] += DPSJ[i][0] + DPSJ[i][1];
						DPS[i + 1][4] += DPSJ[i][3] + DPSJ[i][4];
					}
					else if (S[i] == P) {
						DPSJ[i + 1][1] += DPSJ[i][1] + DPSJ[i][0];
						DPSJ[i + 1][4] += DPSJ[i][4] + DPSJ[i][3];


					}

					if (T[i] < P) {
						DPT[i + 1][1] += DPTJ[i][0] + DPTJ[i][1];
						DPT[i + 1][4] += DPTJ[i][3] + DPTJ[i][4];
					}
					else if (T[i] == P) {
						DPTJ[i + 1][1] += DPTJ[i][1] + DPTJ[i][0];
						DPTJ[i + 1][4] += DPTJ[i][4] + DPTJ[i][3];

					}

					DPSJ[i + 1][1] %= mod;
					DPTJ[i + 1][4] %= mod;
					DPSJ[i + 1][4] %= mod;
					DPTJ[i + 1][1] %= mod;
					DPS[i + 1][1] %= mod;
					DPS[i + 1][4] %= mod;
					DPT[i + 1][1] %= mod;
					DPT[i + 1][4] %= mod;

					DPS[i + 1][2] += DPS[i][2] + DPS[i][1];
					DPT[i + 1][2] += DPT[i][2] + DPT[i][1];
					if (S[i] < B) {
						DPS[i + 1][2] += DPSJ[i][1] + DPSJ[i][2];

					}
					else if (S[i] == B) {
						DPSJ[i + 1][2] += DPSJ[i][1] + DPSJ[i][2];

					}

					if (T[i] < B) {
						DPT[i + 1][2] += DPTJ[i][1] + DPTJ[i][2];

					}
					else if (T[i] == B) {
						DPTJ[i + 1][2] += DPTJ[i][1] + DPTJ[i][2];

					}

					DPSJ[i + 1][2] %= mod;
					DPTJ[i + 1][2] %= mod;
					DPS[i + 1][2] %= mod;
					DPT[i + 1][2] %= mod;

					DPS[i + 1][3] += DPS[i][3] + DPS[i][2];
					DPT[i + 1][3] += DPT[i][3] + DPT[i][2];
					if (S[i] < C) {
						DPS[i + 1][3] += DPSJ[i][2] + DPSJ[i][3];

					}
					else if (S[i] == C) {
						DPSJ[i + 1][3] += DPSJ[i][3] + DPSJ[i][2];

					}

					if (T[i] < C) {
						DPT[i + 1][3] += DPTJ[i][2] + DPTJ[i][3];

					}
					else if (T[i] == C) {
						DPTJ[i + 1][3] += DPTJ[i][3] + DPTJ[i][2];

					}

					DPSJ[i + 1][3] %= mod;
					DPTJ[i + 1][3] %= mod;
					DPS[i + 1][3] %= mod;
					DPT[i + 1][3] %= mod;




				}
				if (DPS[N][4] + DPSJ[N][4] - DPT[N][4] >= 1) {
					//cout << P << B << C << P << endl;
				}
				an += max(DPS[N][4] + DPSJ[N][4] - DPT[N][4],0ll);
				an %= mod;
			}
		}

	}
	cout << an << endl;

}
accuracy: 1
time_ms: 580
memory_kb: 6084
final_rank: 16

code_snippet: // #include <atcoder/all>
// using namespace atcoder;
#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < (n); i++)
#define all(x) (x).begin(), (x).end()
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using vi = vector<int>;
using vll = vector<ll>;
using vvi = vector<vector<int>>;
using vvll = vector<vector<ll>>;
const int inf = 1e9;
const ll lim = 1e18;
int dx[] = {1, 1, 0, -1, -1, -1, 0, 1};
int dy[] = {0, 1, 1, 1, 0, -1, -1, -1};

const int mod = 998244353;

struct mint {
  ll x;  // typedef long long ll;
  mint(ll x = 0) : x((x % mod + mod) % mod) {}
  mint operator-() const { return mint(-x); }
  mint& operator+=(const mint a) {
    if ((x += a.x) >= mod) x -= mod;
    return *this;
  }
  mint& operator-=(const mint a) {
    if ((x += mod - a.x) >= mod) x -= mod;
    return *this;
  }
  mint& operator*=(const mint a) {
    (x *= a.x) %= mod;
    return *this;
  }
  mint operator+(const mint a) const { return mint(*this) += a; }
  mint operator-(const mint a) const { return mint(*this) -= a; }
  mint operator*(const mint a) const { return mint(*this) *= a; }
  mint pow(ll t) const {
    if (!t) return 1;
    mint a = pow(t >> 1);
    a *= a;
    if (t & 1) a *= *this;
    return a;
  }

  // for prime mod
  mint inv() const { return pow(mod - 2); }
  mint& operator/=(const mint a) { return *this *= a.inv(); }
  mint operator/(const mint a) const { return mint(*this) /= a; }
};
istream& operator>>(istream& is, mint& a) { return is >> a.x; }
ostream& operator<<(ostream& os, const mint& a) { return os << a.x; }

int n;
mint dp[10005][4][26][2];
int cv[27];

bool isvowel(int a) { return a == 4 || a == 8 || a == 14 || a == 20 || a == 0; }

mint solve(string& s) {
  rep(i, 10005) rep(j, 4) rep(k, 26) rep(l, 2) dp[i][j][k][l] = 0;

  int a0 = s[0] - 'a';
  mint res = (mint)(a0 - cv[a0]) * (n - 3) * (n - 1) * (n - 2) * 10 / 3;
  dp[0][0][a0][0] = 1;

  rep(i, n - 1) rep(j, 4) rep(k, 26) rep(l, 2) {
    mint pre = dp[i][j][k][l];
    if (pre.x == 0) continue;
    int a = s[i + 1] - 'a';
    rep(nk, 26) {
      int nj = j;
      if (nk != k) nj++;
      if (nj == 4) continue;
      if (nj == 0 || nj == 3) {
        if (isvowel(nk)) continue;
      } else {
        if (!isvowel(nk)) continue;
      }
      if (l == 0 && nk > a) continue;
      int nl = l;
      if (nk < a) nl = 1;
      dp[i + 1][nj][nk][nl] += pre;
    }
  }

  rep(l, 2) res += dp[n - 1][3][a0][l];
  return res;
}

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

  for (char c : "aiueo") {
    int i = c - 'a';
    cv[i + 1] = 1;
  }
  rep(i, 26) cv[i + 1] += cv[i];

  string s, t;
  cin >> n >> s >> t;
  mint a1 = solve(t);
  mint a2 = solve(s);
  mint ans = a1 - a2;
  // cout << a1 << " " << a2 << " " << ans << endl;
  rep(k, 26) ans += dp[n - 1][3][k][0];
  cout << ans << endl;

  return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 19772
final_rank: 2

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

template <int mod = (int)(998244353)>
struct ModInt {
  int x;
  ModInt() : x(0) {}
  ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
  ModInt &operator+=(const ModInt &p) {
    if ((x += p.x) >= mod) x -= mod;
    return *this;
  }
  ModInt &operator-=(const ModInt &p) {
    if ((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }
  ModInt &operator*=(const ModInt &p) {
    x = (int)(1LL * x * p.x % mod);
    return *this;
  }
  ModInt &operator/=(const ModInt &p) {
    *this *= p.inverse();
    return *this;
  }
  ModInt operator-() const { return ModInt(-x); }
  ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }
  ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }
  ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }
  ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }
  bool operator==(const ModInt &p) const { return x == p.x; }
  bool operator!=(const ModInt &p) const { return x != p.x; }
  ModInt inverse() const {
    int a = x, b = mod, u = 1, v = 0, t;
    while (b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }
  ModInt pow(int64_t n) const {
    ModInt res(1), mul(x);
    while (n) {
      if (n & 1) res *= mul;
      mul *= mul;
      n >>= 1;
    }
    return res;
  }
  friend ostream &operator<<(ostream &os, const ModInt &p) { return os << p.x; }
  friend istream &operator>>(istream &is, ModInt &a) {
    int64_t t;
    is >> t;
    a = ModInt<mod>(t);
    return (is);
  }
  static int get_mod() { return mod; }
};

struct Combination {
  vector<ModInt<>> _fact, _rfact, _inv;
  Combination(long long nsize = 5000000)
      : _fact(nsize + 1), _rfact(nsize + 1), _inv(nsize + 1) {
    _fact[0] = _rfact[nsize] = _inv[0] = 1;
    for (int i = 1; i <= nsize; i++) _fact[i] = _fact[i - 1] * i;
    _rfact[nsize] /= _fact[nsize];
    for (int i = nsize - 1; i >= 0; i--) _rfact[i] = _rfact[i + 1] * (i + 1);
    for (int i = 1; i <= nsize; i++) _inv[i] = _rfact[i] * _fact[i - 1];
  }
  inline ModInt<> fact(int k) const { return _fact[k]; }

  inline ModInt<> rfact(int k) const { return _rfact[k]; }

  inline ModInt<> inv(int k) const { return _inv[k]; }

  ModInt<> P(int n, int r) const {
    if (r < 0 || n < r) return 0;
    return fact(n) * rfact(n - r);
  }

  ModInt<> C(int p, int q) const {
    if (q < 0 || p < q) return 0;
    return fact(p) * rfact(q) * rfact(p - q);
  }

  ModInt<> largeC(long long p, long long q) const {
    if (q < 0 || p < q) return 0;
    if (q >= (long long)_fact.size()) q = p - q;
    // if (q >= (long long)5000) q = p - q;
    ModInt<> res = rfact(q);
    for (int i = 0; i < q; ++i) res *= p - i;
    return res;
  }

  // n types,choose r
  ModInt<> H(int n, int r) const {
    if (n < 0 || r < 0) return (0);
    return r == 0 ? 1 : C(n + r - 1, r);
  }

  ModInt<> largeH(long long n, long long r) const {
    if (n < 0 || r < 0) return (0);
    return r == 0 ? 1 : largeC(n + r - 1, r);
  }

  ModInt<> Catalan(int n) {
    // C(2n,n) / (n + 1)
    return fact(2 * n) * rfact(n + 1) * rfact(n);
  }
};
using mint = ModInt<>;

int n;
string mom = "aiueo", chil = "qwrtypsdfghjklzxcvbnm", s, t;
Combination com;

mint solve();
mint calc(char a, char b, char c);

int main() {
  cin >> n >> s >> t;
  cout << solve() << endl;
  return 0;
}

mint solve() {
  if (s > t) return 0;
  mint res = 0;
  for (auto a : chil)
    for (int i = 0; i < 5; ++i)
      for (int j = 0; j < 5; ++j)
        if (i != j) res += calc(a, mom[i], mom[j]);
  return res;
}

mint calc(char a, char b, char c) {
  mint res = com.H(4, n - 4);
  vector<char> v = {a, b, c, a};
  {  // over t
    int state = 0;
    for (int i = 0; i < n; ++i) {
      int nxt = -1;
      for (int j = state; j <= state + (i != 0) && j < 4; ++j)
        if (t[i] < v[j])
          res -= com.H(4 - j, n - i - 1 - (4 - j - 1));
        else if (t[i] == v[j])
          nxt = j;
      if (nxt < 0) break;
      state = nxt;
    }
  }
  {  // before s
    int state = 0;
    for (int i = 0; i < n; ++i) {
      int nxt = -1;
      for (int j = state; j <= state + (i != 0) && j < 4; ++j)
        if (v[j] < s[i])
          res -= com.H(4 - j, n - i - 1 - (4 - j - 1));
        else if (s[i] == v[j])
          nxt = j;
      if (nxt < 0) break;
      state = nxt;
    }
  }
  return res;
}
accuracy: 1
time_ms: 50
memory_kb: 61828
final_rank: 12

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

#define REP(i,n) for(int i=0;i<(n);i++)
#define RREP(i,n) for(int i=(n-1);i>=0;i--)
#define ALL(v) v.begin(),v.end()

using ll=long long;
const ll MOD=998244353;

ll dp[10000][252][2][2];
string siin="bcdfghjklmnpqrstvwxyz";
string boin="aiueo";
void ADD(ll &a,ll b){
  a+=b;
  if(a>=MOD)a-=MOD;
}

int main(){
  int n;cin>>n;
  string s,t;cin>>s>>t;
  if(s>t){
    cout<<0<<endl;
    return 0;
  }
  REP(i,21){
    int p=siin[i];
    if(s[0]<=p&&p<=t[0])
      dp[0][i][s[0]<p][p<t[0]]=1;
  }
  for(int i=1;i<n;i++){
    REP(state,251)REP(S,2)REP(T,2){
      if(!dp[i-1][state][S][T])continue;
      //cout<<i<<" "<<state<<" "<<S<<" "<<T<<" "<<dp[i-1][state][S][T]<<endl;
      if(state<21){
        char p=siin[state];
        if((S||s[i]<=p)&&(T||p<=t[i]))
          ADD(dp[i][state][S|s[i]<p][T|p<t[i]],dp[i-1][state][S][T]);
        REP(qi,5){
          char q=boin[qi];
          if((S||s[i]<=q)&&(T||q<=t[i]))
            ADD(dp[i][21+state*5+qi][S|s[i]<q][T|q<t[i]],dp[i-1][state][S][T]);
        }
      }
      else if(state<21+105){
        int pi=(state-21)/5;
        char p=siin[pi];
        char q=boin[(state-21)%5];

        if((S||s[i]<=q)&&(T||q<=t[i]))
          ADD(dp[i][state][S|s[i]<q][T|q<t[i]],dp[i-1][state][S][T]);
        REP(ri,5){
          char r=boin[ri];
          if(r!=q&&(S||s[i]<=r)&&(T||r<=t[i]))
            ADD(dp[i][21+5*21+pi*5+ri][S|s[i]<r][T|r<t[i]],dp[i-1][state][S][T]);
        }
      }
      else if(state<21+105+105){
        int pi=(state-21-105)/5;
        char p=siin[pi];
        char r=boin[(state-21-105)%5];

        if((S||s[i]<=r)&&(T||r<=t[i]))
          ADD(dp[i][state][S|s[i]<r][T|r<t[i]],dp[i-1][state][S][T]);
        
        if((S||s[i]<=p)&&(T||p<=t[i]))
          ADD(dp[i][21+5*21+5*21+pi][S|s[i]<p][T|p<t[i]],dp[i-1][state][S][T]);
      }
      else{
        int pi=state-21-105-105;
        char p=siin[pi];
        if((S||s[i]<=p)&&(T||p<=t[i]))
          ADD(dp[i][state][S|s[i]<p][T|p<t[i]],dp[i-1][state][S][T]);
      }
    }
  }
  ll ans=0;
  for(int state=21+105+105;state<21+105+105+21;state++)REP(S,2)REP(T,2)
    ADD(ans,dp[n-1][state][S][T]);
  cout<<ans<<endl;
}
accuracy: 1
time_ms: 30
memory_kb: 80672
final_rank: 14

code_snippet: #pragma GCC ta g("avx2")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#define DEBUG
#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
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef pair<int,int> pii;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(int i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
const int inf = (1<<30)-1;
const ll linf = 1LL<<61;
const int MAX = 510000;
int dy[8] = {0,1,0,-1,1,-1,-1,1};
int dx[8] = {-1,0,1,0,1,-1,1,-1};
const double pi = acos(-1);
const double eps = 1e-7;
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T> inline void print(T &a){
    int sz = a.size();
    for(auto itr = a.begin(); itr != a.end(); itr++){
		cout << *itr;
        sz--;
        if(sz) cout << " ";
	}
    cout << "\n";
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){
	cout << a << " " << b << "\n";
}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << a << " " << b << " " << c << "\n";
}
void mark() {cout << "#" << "\n";}
ll pcount(ll x) {return __builtin_popcountll(x);}
//#include <atcoder/maxflow>
//using namespace atcoder;
//const int mod = 1e9 + 7;
const int mod = 998244353;

template <int mod> struct ModInt {
    int x;

    ModInt() : x(0) {}

    ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}

    ModInt &operator+=(const ModInt &p) {
        if((x += p.x) >= mod) x -= mod;
        return *this;
    }

    ModInt &operator-=(const ModInt &p) {
        if((x += mod - p.x) >= mod) x -= mod;
        return *this;
    }

    ModInt &operator*=(const ModInt &p) {
        x = (int)(1LL * x * p.x % mod);
        return *this;
    }

    ModInt &operator/=(const ModInt &p) {
        *this *= p.inverse();
        return *this;
    }

    ModInt operator-() const { return ModInt(-x); }

    ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }

    ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }

    ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }

    ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }

    bool operator==(const ModInt &p) const { return x == p.x; }

    bool operator!=(const ModInt &p) const { return x != p.x; }

    ModInt inverse() const {
        int a = x, b = mod, u = 1, v = 0, t;
        while(b > 0) {
            t = a / b;
            swap(a -= t * b, b);
            swap(u -= t * v, v);
        }
        return ModInt(u);
    }

    ModInt pow(int64_t n) const {
        ModInt ret(1), mul(x);
        while(n > 0) {
            if(n & 1) ret *= mul;
            mul *= mul;
            n >>= 1;
        }
        return ret;
    }

    friend ostream &operator<<(ostream &os, const ModInt &p) {
        return os << p.x;
    }

    friend istream &operator>>(istream &is, ModInt &a) {
        int64_t t;
        is >> t;
        a = ModInt<mod>(t);
        return (is);
    }

    static int get_mod() { return mod; }
};

using mint = ModInt<mod>;

mint dp[2][5][2][2];

string x = "bcdfghjklmnpqrstvwxyz";
string y = "aeiou";

int main(){
    int n; cin >> n;
    string s,t; cin >> s >> t;
    mint ans = 0;
    rep(p,21) rep(q,5) rep(r,5){
        if(q == r) continue;
        rep(i,2) rep(j,5) rep(k,2) rep(l,2) dp[i][j][k][l] = 0;
        dp[0][0][0][0] = 1;
        string u = " "; 
        u += x[p]; u += y[q]; u += y[r]; u += x[p];
        rep(i,n){
            rep(j,5) rep(k,2) rep(l,2) dp[1][j][k][l] = 0;
            rep(j,5) rep(k,2) rep(l,2){
                if(j>0){
                    int nk = 0, nl = 0;
                    if(u[j] > s[i]) nk = 1;
                    else if(u[j] == s[i]) nk = k;
                    else if(k == 1) nk = 1;
                    else nk = -1;
                    if(u[j] < t[i]) nl = 1;
                    else if(u[j] == t[i]) nl = l;
                    else if(l == 1) nl = 1;
                    else nl = -1;
                    if(nk >= 0 && nl >= 0) dp[1][j][nk][nl] += dp[0][j][k][l];
                }
                if(j<4){
                    int nk = 0, nl = 0;
                    if(u[j+1] > s[i]) nk = 1;
                    else if(u[j+1] == s[i]) nk = k;
                    else if(k == 1) nk = 1;
                    else nk = -1;
                    if(u[j+1] < t[i]) nl = 1;
                    else if(u[j+1] == t[i]) nl = l;
                    else if(l == 1) nl = 1;
                    else nl = -1;
                    if(nk >= 0 && nl >= 0) dp[1][j+1][nk][nl] += dp[0][j][k][l];
                }
            }
            swap(dp[0],dp[1]);
        }
        rep(k,2) rep(l,2) ans += dp[0][4][k][l];
    }
    cout << ans << endl;
}
accuracy: 1
time_ms: 150
memory_kb: 3444
final_rank: 5

code_snippet: #line 1 "h.cpp"
#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 = 998244353;
const int dx[4] = {1, 0, -1, 0};
const int dy[4] = {0, 1, 0, -1};

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

#line 1 "/home/siro53/kyo-pro/compro_library/math/modint.hpp"
template <int mod> struct ModInt {
    int x;
    ModInt() : x(0) {}
    ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
    ModInt &operator+=(const ModInt &p) {
        if((x += p.x) >= mod)
            x -= mod;
        return *this;
    }
    ModInt &operator-=(const ModInt &p) {
        if((x += mod - p.x) >= mod)
            x -= mod;
        return *this;
    }
    ModInt &operator*=(const ModInt &p) {
        x = (int)(1LL * x * p.x % mod);
        return *this;
    }
    ModInt &operator/=(const ModInt &p) {
        *this *= p.inv();
        return *this;
    }
    ModInt operator-() const { return ModInt(-x); }
    ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }
    ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }
    ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }
    ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }
    bool operator==(const ModInt &p) const { return x == p.x; }
    bool operator!=(const ModInt &p) const { return x != p.x; }
    ModInt inv() const {
        int a = x, b = mod, u = 1, v = 0, t;
        while(b > 0) {
            t = a / b;
            swap(a -= t * b, b);
            swap(u -= t * v, v);
        }
        return ModInt(u);
    }
    ModInt pow(int64_t n) const {
        ModInt ret(1), mul(x);
        while(n > 0) {
            if(n & 1)
                ret *= mul;
            mul *= mul;
            n >>= 1;
        }
        return ret;
    }
    friend ostream &operator<<(ostream &os, const ModInt &p) {
        return os << p.x;
    }
    friend istream &operator>>(istream &is, ModInt &a) {
        int64_t t;
        is >> t;
        a = ModInt<mod>(t);
        return (is);
    }
    static int get_mod() { return mod; }
};
#line 72 "h.cpp"
using mint = ModInt<MOD>;

int N;
string s, t;
mint dp[10010][2][2][5];

mint solve(char p, char q, char r) {
    REP(i, N+1) REP(j, 2) REP(k, 2) REP(l, 5) dp[i][j][k][l] = 0;
    string mp = "-";
    mp += p; mp += q; mp += r; mp += p; 
    dp[0][1][1][0] = 1;
    REP(i, N) {
        int cs = s[i] - 'a';
        int ct = t[i] - 'a';
        REP(j, 2) REP(k, 2) REP(l, 5) {
            int c = mp[l] - 'a';
            if(j == 1 and c < cs) continue;
            if(k == 1 and c > ct) continue;
            if(l == 0) continue;
            int nj = j;
            if(j == 1 and c > cs) nj = 0;
            int nk = k;
            if(k == 1 and c < ct) nk = 0;
            dp[i+1][nj][nk][l] += dp[i][j][k][l];
        } 
        REP(j, 2) REP(k, 2) REP(l, 4) {
            int c = mp[l+1] - 'a';
            if(j == 1 and c < cs) continue;
            if(k == 1 and c > ct) continue;
            int nj = j;
            if(j == 1 and c > cs) nj = 0;
            int nk = k;
            if(k == 1 and c < ct) nk = 0;
            dp[i+1][nj][nk][l+1] += dp[i][j][k][l];
        }
    }
    mint ret = 0;
    REP(j, 2) REP(k, 2) ret += dp[N][j][k][4];
    return ret;
}

int main() {
    cin >> N >> s >> t;
    const string boin = "aeiou";
    mint ans = 0;
    for(char p = 'a'; p <= 'z'; p++) {
        bool f = false;
        for(char c : boin) if(p == c) f = true;
        if(f) continue;
        REP(i, 5) REP(j, 5) {
            if(i == j) continue;
            ans += solve(p, boin[i], boin[j]);
        }
    }
    cout << ans << endl;
}
accuracy: 1
time_ms: 340
memory_kb: 4264
final_rank: 10

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

using ll = long long int;
using ull = unsigned long long int;
using P = pair<ll, ll>;
using P3 = pair<int,P>;
using PP = pair<P, P>;
constexpr int INF32 = 1 << 30;
constexpr ll INF64 = 1LL << 60;
// constexpr ll MOD = 1000000007;
constexpr ll MOD = 998244353;
constexpr int di[] = {0, 1, 0, -1};
constexpr int dj[] = {1, 0, -1, 0};
constexpr int di8[] = {0, 1, 1, 1, 0, -1, -1, -1};
constexpr int dj8[] = {1, 1, 0, -1, -1, -1, 0, 1};
constexpr double EPS = 1e-9;
const double PI = acos(-1);

#define ALL(v) (v).begin(),(v).end()
#define REP(i,n) for(int i=0,i_len=n; i<i_len; ++i)

template<typename T1,typename T2> bool chmax(T1 &a, T2 b) { if (a<b) { a=b; return 1; } return 0; }
template<typename T1,typename T2> bool chmin(T1 &a, T2 b) { if (b<a) { a=b; return 1; } return 0; }

template <std::uint_fast64_t Modulus> class modint {
  using u64 = std::uint_fast64_t;

public:
  u64 a;

  constexpr modint(const u64 x = 0) noexcept : a(x % Modulus) {}
  constexpr u64 &value() noexcept { return a; }
  constexpr const u64 &value() const noexcept { return a; }
  constexpr modint operator+(const modint rhs) const noexcept {
    return modint(*this) += rhs;
  }
  constexpr modint operator-(const modint rhs) const noexcept {
    return modint(*this) -= rhs;
  }
  constexpr modint operator*(const modint rhs) const noexcept {
    return modint(*this) *= rhs;
  }
  constexpr modint operator/(const modint rhs) const noexcept {
    return modint(*this) /= rhs;
  }
  constexpr modint &operator+=(const modint rhs) noexcept {
    a += rhs.a;
    if (a >= Modulus) {
      a -= Modulus;
    }
    return *this;
  }
  constexpr modint &operator-=(const modint rhs) noexcept {
    if (a < rhs.a) {
      a += Modulus;
    }
    a -= rhs.a;
    return *this;
  }
  constexpr modint &operator*=(const modint rhs) noexcept {
    a = a * rhs.a % Modulus;
    return *this;
  }
  constexpr modint &operator/=(modint rhs) noexcept {
    u64 exp = Modulus - 2;
    while (exp) {
      if (exp % 2) {
        *this *= rhs;
      }
      rhs *= rhs;
      exp /= 2;
    }
    return *this;
  }
};

using mint = modint<MOD>;

vector<int> vs, cs;

mint f(string s, int p){
    mint dp[10001][4][26][2];
    dp[1][0][p][p<(s[0]-'a')] = 1;
    int n = s.size();
    for(int i=1;i<n;i++){
        int x = s[i]-'a';
        for(int j=0;j<4;j++){
            for(int k=0;k<2;k++){
                if(j==0 || j==3){
                    if(k==1 || p<=x){
                        dp[i+1][j][p][k||(p<x)] += dp[i][j][p][k];
                    }
                    if(j==0){
                        for(auto v : vs){
                            if(k==0 && x<v) continue;
                            dp[i+1][j+1][v][k||(v<x)] += dp[i][j][p][k];
                            // cout << dp[i][j][p][k].value() << endl;
                        }
                    }
                }
                else if(j==1){
                    for(auto v1 : vs){
                        if(k==1 || v1<=x) dp[i+1][j][v1][k||(v1<x)] += dp[i][j][v1][k];
                        for(auto v2 : vs){
                            if(v1 == v2) continue;
                            if(k==0 && x<v2) continue;
                            dp[i+1][j+1][v2][k||(v2<x)] += dp[i][j][v1][k];
                        }
                    }
                }else{
                    for(auto v : vs){
                        if(k==1 || v<=x) dp[i+1][j][v][k||(v<x)] += dp[i][j][v][k];
                        if(k==1 || p<=x) dp[i+1][j+1][p][k||(p<x)] += dp[i][j][v][k];
                    }
                }
            }
        }
    }
    mint res = 0;
    for(int i=0;i<26;i++) res += dp[n][3][i][0] + dp[n][3][i][1];
    return res;
}

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n;
    string s, t;
    cin >> n >> s >> t;
    mint fs = 0, ft = 0;
    for(int i=0;i<26;i++){
        if(i==0) vs.push_back(i);
        else if(i=='i'-'a') vs.push_back(i);
        else if(i=='u'-'a') vs.push_back(i);
        else if(i=='e'-'a') vs.push_back(i);
        else if(i=='o'-'a') vs.push_back(i);
        else cs.push_back(i);
    }
    sort(ALL(cs));
    sort(ALL(vs));
    if(s[n-1]-'a' > 0) s[n-1]--;
    for(int i : cs){
      if(i > s[0]-'a') break;
      fs += f(s, i);
    }
    for(int i : cs){
      if(i > t[0]-'a') break;
      ft += f(t, i);
    }
    cout << (ft-fs).value() << endl;
    return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 19712
final_rank: 6

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

#include <cassert>
#include <numeric>
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif


#include <utility>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}

struct barrett {
    unsigned int _m;
    unsigned long long im;

    explicit barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

    unsigned int umod() const { return _m; }

    unsigned int mul(unsigned int a, unsigned int b) const {

        unsigned long long z = a;
        z *= b;
#ifdef _MSC_VER
        unsigned long long x;
        _umul128(z, im, &x);
#else
        unsigned long long x =
            (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
        unsigned int v = (unsigned int)(z - x * _m);
        if (_m <= v) v += _m;
        return v;
    }
};

constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}

constexpr bool is_prime_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long d = n - 1;
    while (d % 2 == 0) d /= 2;
    constexpr long long bases[3] = {2, 7, 61};
    for (long long a : bases) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) {
            y = y * y % n;
            t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
            return false;
        }
    }
    return true;
}
template <int n> constexpr bool is_prime = is_prime_constexpr(n);

constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};

    long long s = b, t = a;
    long long m0 = 0, m1 = 1;

    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b


        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}

constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) {
                x /= i;
            }
        }
    }
    if (x > 1) {
        divs[cnt++] = x;
    }
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m> constexpr int primitive_root = primitive_root_constexpr(m);

unsigned long long floor_sum_unsigned(unsigned long long n,
                                      unsigned long long m,
                                      unsigned long long a,
                                      unsigned long long b) {
    unsigned long long ans = 0;
    while (true) {
        if (a >= m) {
            ans += n * (n - 1) / 2 * (a / m);
            a %= m;
        }
        if (b >= m) {
            ans += n * (b / m);
            b %= m;
        }

        unsigned long long y_max = a * n + b;
        if (y_max < m) break;
        n = (unsigned long long)(y_max / m);
        b = (unsigned long long)(y_max % m);
        std::swap(m, a);
    }
    return ans;
}

}  // namespace internal

}  // namespace atcoder


#include <cassert>
#include <numeric>
#include <type_traits>

namespace atcoder {

namespace internal {

#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value ||
                                  std::is_same<T, __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int128 =
    typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                  std::is_same<T, unsigned __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value,
                              __uint128_t,
                              unsigned __int128>;

template <class T>
using is_integral = typename std::conditional<std::is_integral<T>::value ||
                                                  is_signed_int128<T>::value ||
                                                  is_unsigned_int128<T>::value,
                                              std::true_type,
                                              std::false_type>::type;

template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                 std::is_signed<T>::value) ||
                                                    is_signed_int128<T>::value,
                                                std::true_type,
                                                std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value,
    make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value,
                              std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

#else

template <class T> using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int =
    typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value &&
                                  std::is_unsigned<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value,
                                              std::make_unsigned<T>,
                                              std::common_type<T>>::type;

#endif

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;

template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;

template <class T> using to_unsigned_t = typename to_unsigned<T>::type;

}  // namespace internal

}  // namespace atcoder


namespace atcoder {

namespace internal {

struct modint_base {};
struct static_modint_base : modint_base {};

template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
    using mint = static_modint;

  public:
    static constexpr int mod() { return m; }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    static_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    static_modint(T v) {
        long long x = (long long)(v % (long long)(umod()));
        if (x < 0) x += umod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    static_modint(T v) {
        _v = (unsigned int)(v % umod());
    }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v -= rhs._v;
        if (_v >= umod()) _v += umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        _v = (unsigned int)(z % umod());
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        if (prime) {
            assert(_v);
            return pow(umod() - 2);
        } else {
            auto eg = internal::inv_gcd(_v, m);
            assert(eg.first == 1);
            return eg.second;
        }
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static constexpr unsigned int umod() { return m; }
    static constexpr bool prime = internal::is_prime<m>;
};

template <int id> struct dynamic_modint : internal::modint_base {
    using mint = dynamic_modint;

  public:
    static int mod() { return (int)(bt.umod()); }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = internal::barrett(m);
    }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    dynamic_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        long long x = (long long)(v % (long long)(mod()));
        if (x < 0) x += mod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        _v = (unsigned int)(v % mod());
    }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v += mod() - rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        _v = bt.mul(_v, rhs._v);
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        auto eg = internal::inv_gcd(_v, mod());
        assert(eg.first == 1);
        return eg.second;
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static internal::barrett bt;
    static unsigned int umod() { return bt.umod(); }
};
template <int id> internal::barrett dynamic_modint<id>::bt(998244353);

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;

template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;

template <class> struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};

template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;

}  // namespace internal

}  // namespace atcoder

using namespace std;
using namespace atcoder;
#define rep(i,n) for(int i = 0; i < int(n); ++i)
#define rrep(i,n) for(int i = int(n)-1; i >= 0; --i)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
template<class T> void chmax(T& a, const T& b) {a = max(a, b);}
template<class T> void chmin(T& a, const T& b) {a = min(a, b);}
using ll = long long;
using P = pair<int,int>;
using VI = vector<int>;
using VVI = vector<VI>;
using VL = vector<ll>;
using VVL = vector<VL>;
using mint = modint998244353;

using D = array<array<array<array<array<mint, 26>, 4>, 2>, 2>, 26>;

bool is_vowel[26];
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    for(char c: "aeiou"s) is_vowel[c - 'a'] = true;
    int n;
    cin >> n;
    string s, t;
    cin >> s >> t;
    D dp;
    {
        int x = s[0] - 'a', y = t[0] - 'a';
        rep(i, 26) {
            if (i < x || i > y || is_vowel[i]) continue;
            int b1 = i > x;
            int b2 = i < y;
            dp[i][b1][b2][0][i] = 1;
        }
    }
    for(int i = 1; i < n; i++) {
        int x = s[i] - 'a', y = t[i] - 'a';
        D ndp;
        rep(c_first, 26) rep(b1, 2) rep(b2, 2) rep(k, 4) rep(c_last, 26) if (dp[c_first][b1][b2][k][c_last].val()) rep(c, 26) {
            int nb1;
            if (b1 == 0) {
                if (c < x) continue;
                if (c == x) nb1 = 0;
                else nb1 = 1;
            } else {
                nb1 = 1;
            }
            int nb2;
            if (b2 == 0) {
                if (c > y) continue;
                if (c == y) nb2 = 0;
                else nb2 = 1;
            } else {
                nb2 = 1;
            }
            int nk;
            if (c == c_last) {
                nk = k;
            } else {
                if (k == 3) continue;
                nk = k + 1;
                if (k == 0) {
                    if (!is_vowel[c]) continue;
                } else if (k == 1) {
                    if (c == c_last || !is_vowel[c]) continue;
                } else if (k == 2) {
                    if (c != c_first) continue;
                }
            }
            ndp[c_first][nb1][nb2][nk][c] += dp[c_first][b1][b2][k][c_last];
        }
        dp = ndp;
    }
    mint ans;
    rep(c_first, 26) rep(b1, 2) rep(b2, 2) {
        int k = 3;
        rep(c, 26) ans += dp[c_first][b1][b2][k][c];
    }
    cout << ans.val() << endl;
}
accuracy: 1
time_ms: 140
memory_kb: 3580
final_rank: 4

code_snippet: #include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstdlib>
#include <cassert>
#include <vector>
#include <list>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <bitset>
#include <string>
#include <algorithm>
#include <utility>
#include <complex>
#include <unordered_set>
#include <unordered_map>
#define rep(x, s, t) for(ll x = (s); (x) <= (t); (x)++)
#define per(x, s, t) for(ll x = (s); (x) >= (t); (x)--)
#define reps(x, s) for(ll x = 0; (x) < (ll)(s).size(); (x)++)
#define chmin(x, y) (x) = min((x), (y))
#define chmax(x, y) (x) = max((x), (y))
#define sz(x) ((ll)(x).size())
#define all(x) (x).begin(),(x).end()
#define outl(...) dump_func(__VA_ARGS__)
#define outf(x) cout << fixed << setprecision(16) << (x) << endl
#define inf 2e18
#define eps 1e-9
const double PI = 3.1415926535897932384626433;

using namespace std;

typedef long long llint;
typedef long long ll;
typedef pair<ll, ll> P;

struct edge{
	ll to, cost;
	edge(){}
	edge(ll a, ll b){ to = a, cost = b;}
};
const int dx[] = {1, 0, -1, 0}, dy[] = {0, -1, 0, 1};

//const int mod = 1000000007;
const int mod = 998244353;

struct mint{
	int x;
	mint(ll y = 0){if(y < 0 || y >= mod) y = (y%mod+mod)%mod; x = y;}
	mint(const mint &ope) {x = ope.x;}

	mint operator-(){return mint(-x);}
	mint operator+(const mint &ope){return mint(x) += ope;}
	mint operator-(const mint &ope){return mint(x) -= ope;}
	mint operator*(const mint &ope){return mint(x) *= ope;}
	mint operator/(const mint &ope){return mint(x) /= ope;}
	mint& operator+=(const mint &ope){
		x += ope.x;
		if(x >= mod) x -= mod;
		return *this;
	}
	mint& operator-=(const mint &ope){
		x += mod - ope.x;
		if(x >= mod) x -= mod;
		return *this;
	}
	mint& operator*=(const mint &ope){
		ll tmp = x;
		tmp *= ope.x, tmp %= mod;
		x = tmp;
		return *this;
	}
	mint& operator/=(const mint &ope){
		ll n = mod-2; mint mul = ope;
		while(n){
			if(n & 1) *this *= mul;
			mul *= mul;
			n >>= 1;
		}
		return *this;
	}
	mint inverse(){return mint(1) / *this;}
	bool operator ==(const mint &ope){return x == ope.x;}
	bool operator !=(const mint &ope){return x != ope.x;}
	bool operator <(const mint &ope){return x < ope.x;}
};
mint modpow(mint a, ll n){
	if(n == 0) return mint(1);
	if(n % 2) return a * modpow(a, n-1);
	else return modpow(a*a, n/2);
}
istream& operator >>(istream &is, mint &ope){
	ll t; is >> t, ope.x = t;
	return is;
}
ostream& operator <<(ostream &os, mint &ope){return os << ope.x;}
ostream& operator <<(ostream &os, const mint &ope){return os << ope.x;}

vector<mint> fact, fact_inv;
void make_fact(int n){
	fact.resize(n+1), fact_inv.resize(n+1);
	fact[0] = mint(1); rep(i, 1, n) fact[i] = fact[i-1] * mint(i);
	fact_inv[n] = fact[n].inverse(); per(i, n-1, 0) fact_inv[i] = fact_inv[i+1] * mint(i+1);
}
mint comb(int n, int k){ if(n < 0 || k < 0 || n < k) return mint(0); return fact[n] * fact_inv[k] * fact_inv[n-k];}
mint perm(int n, int k){ return comb(n, k) * fact[k]; }

vector<int> prime, pvec;
void make_prime(int n){
	prime.resize(n+1);
	rep(i, 2, n){
		if(prime[i]) continue;
		for(int j = i; j <= n; j+=i) prime[j] = i;
	}
	rep(i, 2, n) if(prime[i] == i) pvec.push_back(i);
}

bool exceed(ll x, ll y, ll m){return x >= m / y + 1;}
void mark(){ cout << "*" << endl; }
void yes(){ cout << "YES" << endl; }
void no(){ cout << "NO" << endl; }
ll floor(ll a, ll b){ if(b < 0) a *= -1, b *= -1; if(a >= 0) return a/b; else return -((-a+b-1)/b); }
ll ceil(ll a, ll b){ if(b < 0) a *= -1, b *= -1; if(a >= 0) return (a+b-1)/b; else return -((-a)/b); }
ll modulo(ll a, ll b){ b = abs(b); return a - floor(a, b) * b; }
ll sgn(ll x){ if(x > 0) return 1; if(x < 0) return -1; return 0;}
ll gcd(ll a, ll b){if(b == 0) return a; return gcd(b, a%b);}
ll lcm(ll a, ll b){return a/gcd(a, b)*b;}
ll digitnum(ll x, ll b = 10){ll ret = 0; for(; x; x /= b) ret++; return ret;}
ll digitsum(ll x, ll b = 10){ll ret = 0; for(; x; x /= b) ret += x % b; return ret;}
string lltos(ll x){string ret; for(;x;x/=10) ret += x % 10 + '0'; reverse(ret.begin(), ret.end()); return ret;}
ll stoll(string &s){ll ret = 0; for(auto c : s) ret *= 10, ret += c - '0'; return ret;}
template<typename T>
void uniq(T &vec){ sort(vec.begin(), vec.end()); vec.erase(unique(vec.begin(), vec.end()), vec.end());}

template<class S, class T> pair<S, T>& operator+=(pair<S,T> &s, const pair<S,T> &t){
	s.first += t.first, s.second += t.second;
	return s;
}
template<class S, class T> pair<S, T>& operator-=(pair<S,T> &s, const pair<S,T> &t){
	s.first -= t.first, s.second -= t.second;
	return s;
}
template<class S, class T> pair<S, T> operator+(const pair<S,T> &s, const pair<S,T> &t){
	return pair<S,T>(s.first+t.first, s.second+t.second);
}
template<class S, class T> pair<S, T> operator-(const pair<S,T> &s, const pair<S,T> &t){
	return pair<S,T>(s.first-t.first, s.second-t.second);
}
template<typename T>
ostream& operator << (ostream& os, vector<T>& vec) {
	reps(i, vec) os << vec[i] << (i + 1 == vec.size() ? "" : " "); return os;
}
template<typename T>
ostream& operator << (ostream& os, const vector<T>& vec) {
	reps(i, vec) os << vec[i] << (i + 1 == vec.size() ? "" : " "); return os;
}
template<typename T>
ostream& operator << (ostream& os, deque<T>& deq) {
	reps(i,  deq) os << deq[i] << (i + 1 == deq.size() ? "" : " "); return os;
}
template<typename T, typename U>
ostream& operator << (ostream& os, pair<T, U>& pair_var) {
	os << "(" << pair_var.first << ", " << pair_var.second << ")";
	return os;
}
template<typename T, typename U>
ostream& operator << (ostream& os, const pair<T, U>& pair_var) {
	os << "(" << pair_var.first << ", " << pair_var.second << ")";
	return os;
}
template<typename T, typename U>
ostream& operator << (ostream& os, map<T, U>& map_var) {
	for(typename map<T, U>::iterator itr = map_var.begin(); itr != map_var.end(); itr++) {
		os << "(" << itr->first << ", " << itr->second << ")";
		itr++; if(itr != map_var.end()) os << ","; itr--;
	}
	return os;
}
template<typename T>
ostream& operator << (ostream& os, set<T>& set_var) {
	for(typename set<T>::iterator itr = set_var.begin(); itr != set_var.end(); itr++) {
		os << *itr; ++itr; if(itr != set_var.end()) os << " "; itr--;
	}
	return os;
}
template<typename T>
ostream& operator << (ostream& os, multiset<T>& set_var) {
	for(typename multiset<T>::iterator itr = set_var.begin(); itr != set_var.end(); itr++) {
		os << *itr; ++itr; if(itr != set_var.end()) os << " "; itr--;
	}
	return os;
}
template<typename T>
void outa(T a[], ll s, ll t){rep(i, s, t){ cout << a[i]; if(i < t) cout << " ";}cout << endl;}
void dump_func(){cout << endl;}
template <class Head, class... Tail>
void dump_func(Head &&head, Tail &&... tail) {
	cout << head;
	if(sizeof...(Tail) > 0) cout << " ";
	dump_func(std::move(tail)...);
}

ll n;
string s, t;
string v = "aiueo";
mint dp[10005][12][2];

mint calc(string s)
{
	mint ret = 0;
	rep(z, 0, 25){
		char p = z + 'a';

		bool flag = false;
		rep(j, 0, 4) if(v[j] == p) flag = true;
		if(flag) continue;

		rep(i, 0, n) rep(j, 0, 11) rep(k, 0, 1) dp[i][j][k] = 0;
		dp[0][0][0] = 1;

		rep(i, 0, n-1){
			rep(j, 0, 11){
				rep(k, 0, 1){
					if(dp[i][j][k] == mint(0)) continue;
					//outl(p, i, j, k, dp[i][j][k]);

					char c;
					rep(l, 0, 11){
						if(l == 0 || l == 11) c = p;
						else c = v[l%5];

						if(i == 0 && l != 0) continue;
						if(j == 0 && l >= 6) continue;
						if(j >= 1 && j <= 5){
							if(l >= 1 && l <= 5 && j != l) continue;
							if(l >= 6 && l <= 10 && j%5 == l%5) continue;
							if(l == 0 || l == 11) continue;
						}
						if(j >= 6 && j <= 10){
							if(l >= 6 && l <= 10 && j != l) continue;
							if(l <= 5) continue;
						}
						if(j == 11 && l != 11)  continue;

						ll nk = k;
						if(k == 0 && c > s[i]) continue;
						if(c < s[i]) nk = 1;

						//outl(l, c);

						dp[i+1][l][nk] += dp[i][j][k];
					}
				}
			}
		}
		ret += dp[n][11][0] + dp[n][11][1];
	}

	return ret;
}

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

	cin >> n >> s >> t;

	bool flag = false;
	s[sz(s)-1]--;
	per(i, sz(s)-1, 0){
		if(s[i] < 'a'){
			s[i] = 'z';
			if(i == 0){
				flag = true;
				break;
			}
			s[i-1]--;
		}
		else break;
	}

	mint ans = calc(t);
	if(!flag) ans -= calc(s);
	outl(ans);

	return 0;
}
accuracy: 1
time_ms: 130
memory_kb: 4388
final_rank: 3

code_snippet: // g++ -std=c++11 a.cpp
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
#include<map>
#include<set>
#include<unordered_map>
#include<utility>
#include<cmath>
#include<random>
#include<cstring>
#include<queue>
#include<stack>
#include<bitset>
#include<cstdio>
#include<sstream>
#include<random>
#include<iomanip>
#include<assert.h>
#include<typeinfo>
#include<list>
#define loop(i,a,b) for(int i=a;i<b;i++)
#define rep(i,a) loop(i,0,a)
#define FOR(i,a) for(auto i:a)
#define pb push_back
#define all(in) in.begin(),in.end()
#define shosu(x) fixed<<setprecision(x)
#define show1d(v) {rep(_,v.size())cout<<" "<<v[_];cout<<endl;}
#define show2d(v) {rep(__,v.size())show1d(v[__]);}
using namespace std;
typedef long long ll;
#define int ll
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<pii> vp;
typedef vector<vp> vvp;
typedef vector<string> vs;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef pair<int,pii> pip;
typedef vector<pip>vip;
typedef tuple<int,int,int> tp;
typedef vector<tp> vt;
typedef vector<vt>vvt;
template<typename A,typename B>bool cmin(A &a,const B &b){return a>b?(a=b,true):false;}
template<typename A,typename B>bool cmax(A &a,const B &b){return a<b?(a=b,true):false;}
const double PI=acos(-1);
const long double EPS=1e-18;
int inf = sizeof(int) == sizeof(long long) ? 2e18 : 1e9+10;
int dx[]={-1,0,1,0};
int dy[]={0,1,0,-1};
#define yes cout<<"Yes\n"
#define no cout<<"No\n"

int n,MOD=998244353;
vi c(26);
int isTUAT(string s){
	char a=s[0];
	int idx=0;
	while(idx<s.size()&&s[idx]==a)idx++;
	if(idx==s.size())return 0;

	char b=s[idx];
	while(idx<s.size()&&s[idx]==b)idx++;
	if(idx==s.size())return 0;

	char c=s[idx];
	while(idx<s.size()&&s[idx]==c)idx++;
	if(idx==s.size())return 0;

	while(idx<s.size()&&s[idx]==a)idx++;
	return idx==s.size();
}
int dp[10010][26][5][4][2];
int f(string s){
	rep(i,10010)rep(j,26)rep(k,5)rep(l,4)rep(m,2)
		dp[i][j][k][l][m]=0;
	dp[0][0][0][0][0]=1;

	rep(i,n)rep(j,26)rep(k,5)rep(l,4)rep(m,2)rep(x,26)if(dp[i][j][k][l][m]){
		if(!m&&s[i]-'a'<x)continue;
		int I=i+1,J,K,L,M=m||(s[i]-'a')!=x;
		if(l==0){
			if(i==0){
				if(c[x])continue;
				J=x,K=0,L=0;
			}else{
				if(j!=x){
					if(!c[x])continue;
					J=j,K=c[x]-1,L=1;
				}else{
					J=j,K=k,L=l;
				}
			}
		}else if(l==1){
			if(!c[x])continue;
			if(c[x]-1==k){
				J=j,K=k,L=l;
			}else{
				J=j,K=c[x]-1,L=l+1;
			}
		}else if(l==2){
			if(c[x]){
				if(c[x]-1!=k)continue;
				J=j,K=k,L=l;
			}else{
				if(j!=x)continue;
				J=j,K=0,L=l+1;
			}
		}else if(l==3){
			if(j!=x)continue;
			J=j,K=0,L=l;
		}
		// cout<<i<<" "<<j<<" "<<k<<" "<<l<<" "<<m<<" "<<x<<endl;
		// cout<<" "<<I<<" "<<J<<" "<<K<<" "<<L<<" "<<M<<endl;
		(dp[I][J][K][L][M]+=dp[i][j][k][l][m])%=MOD;
	}
	int sum=0;
	rep(i,26)rep(j,2)(sum+=dp[n][i][0][3][j])%=MOD;
	return sum;
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);

	c['a'-'a']=1;
	c['i'-'a']=2;
	c['u'-'a']=3;
	c['e'-'a']=4;
	c['o'-'a']=5;

	string s,t;
	cin>>n>>s>>t;
	cout<<(f(t)-f(s)+isTUAT(s)+MOD)%MOD<<endl;
}
accuracy: 1
time_ms: 500
memory_kb: 84828
final_rank: 18

code_snippet: // g++ -std=c++11 a.cpp
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
#include<map>
#include<set>
#include<unordered_map>
#include<utility>
#include<cmath>
#include<random>
#include<cstring>
#include<queue>
#include<stack>
#include<bitset>
#include<cstdio>
#include<sstream>
#include<random>
#include<iomanip>
#include<assert.h>
#include<typeinfo>
#include<list>
#define loop(i,a,b) for(int i=a;i<b;i++)
#define rep(i,a) loop(i,0,a)
#define FOR(i,a) for(auto i:a)
#define pb push_back
#define all(in) in.begin(),in.end()
#define shosu(x) fixed<<setprecision(x)
#define show1d(v) {rep(_,v.size())cout<<" "<<v[_];cout<<endl;}
#define show2d(v) {rep(__,v.size())show1d(v[__]);}
using namespace std;
typedef long long ll;
#define int ll
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<pii> vp;
typedef vector<vp> vvp;
typedef vector<string> vs;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef pair<int,pii> pip;
typedef vector<pip>vip;
typedef tuple<int,int,int> tp;
typedef vector<tp> vt;
typedef vector<vt>vvt;
template<typename A,typename B>bool cmin(A &a,const B &b){return a>b?(a=b,true):false;}
template<typename A,typename B>bool cmax(A &a,const B &b){return a<b?(a=b,true):false;}
const double PI=acos(-1);
const long double EPS=1e-18;
int inf = sizeof(int) == sizeof(long long) ? 2e18 : 1e9+10;
int dx[]={-1,0,1,0};
int dy[]={0,1,0,-1};
#define yes cout<<"Yes\n"
#define no cout<<"No\n"

int n,MOD=998244353;
vi c(26);
int isTUAT(string s){
	char a=s[0];
	int idx=0;
	while(idx<s.size()&&s[idx]==a)idx++;
	if(idx==s.size())return 0;

	char b=s[idx];
	while(idx<s.size()&&s[idx]==b)idx++;
	if(idx==s.size())return 0;

	char c=s[idx];
	while(idx<s.size()&&s[idx]==c)idx++;
	if(idx==s.size())return 0;

	while(idx<s.size()&&s[idx]==a)idx++;
	return idx==s.size();
}
int dp[10010][26][5][4][2];
int f(string s){
	rep(i,10010)rep(j,26)rep(k,5)rep(l,4)rep(m,2)
		dp[i][j][k][l][m]=0;
	dp[0][0][0][0][0]=1;

	rep(i,n)rep(j,26)rep(k,5)rep(l,4)rep(m,2)rep(x,26)if(dp[i][j][k][l][m]){
		if(!m&&s[i]-'a'<x)continue;
		int I=i+1,J,K,L,M=m||(s[i]-'a')!=x;
		if(l==0){
			if(i==0){
				if(c[x])continue;
				J=x,K=0,L=0;
			}else{
				if(j!=x){
					if(!c[x])continue;
					J=j,K=c[x]-1,L=1;
				}else{
					J=j,K=k,L=l;
				}
			}
		}else if(l==1){
			if(!c[x])continue;
			if(c[x]-1==k){
				J=j,K=k,L=l;
			}else{
				J=j,K=c[x]-1,L=l+1;
			}
		}else if(l==2){
			if(c[x]){
				if(c[x]-1!=k)continue;
				J=j,K=k,L=l;
			}else{
				if(j!=x)continue;
				J=j,K=0,L=l+1;
			}
		}else if(l==3){
			if(j!=x)continue;
			J=j,K=0,L=l;
		}
		// cout<<i<<" "<<j<<" "<<k<<" "<<l<<" "<<m<<" "<<x<<endl;
		// cout<<" "<<I<<" "<<J<<" "<<K<<" "<<L<<" "<<M<<endl;
		(dp[I][J][K][L][M]+=dp[i][j][k][l][m])%=MOD;
	}
	int sum=0;
	rep(i,26)rep(j,2)(sum+=dp[n][i][0][3][j])%=MOD;
	return sum;
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);

	c['a'-'a']=1;
	c['i'-'a']=2;
	c['u'-'a']=3;
	c['e'-'a']=4;
	c['o'-'a']=5;

	string s,t;
	cin>>n>>s>>t;
	cout<<f(t)-f(s)+isTUAT(s)<<endl;
}
accuracy: 0.47368421052631576
time_ms: 310
memory_kb: 84720
final_rank: 20

code_snippet: //#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 998244353;
const ll INF = mod * mod;
typedef pair<int, int>P;

#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 0.01;
const ld pi = acosl(-1.0);

ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	ll n;
	modint() :n(0) { ; }
	modint(ll m) :n(m) {
		if (n >= mod)n %= mod;
		else if (n < 0)n = (n % mod + mod) % mod;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 4;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}

string b = "aiueo";
string cc;

modint dp[1 << 14][4][2];
modint calc(string s) {
	//less than or equal
	int n = s.size();
	modint ans = 0;
	rep(i, 21) {
		rep(j, 5)rep(k, 5)if (j != k) {
			rep(x, n + 1)rep(y, 4)rep(z, 2)dp[x][y][z] = 0;
			dp[0][0][0] = 1;
			string ss;
			ss.push_back(cc[i]);
			ss.push_back(b[j]);
			ss.push_back(b[k]);
			ss.push_back(cc[i]);
			rep(x, n) {
				rep(y, 4) {
					rep(z, 2) {
						rep(ad, 2) {
							if (x == 0 && ad)continue;
							if (y == 3 && ad)continue;
							int nx = x + 1;
							int ny = y + ad;
							int nz = z;
							char c = ss[ny];
							if (c < s[x])nz = 1;
							else if (c > s[x] && z == 0)continue;
							dp[nx][ny][nz] += dp[x][y][z];
						}
					}
				}
			}
			ans += dp[n][3][0]+dp[n][3][1];
		}
	}
	return ans;
}
void solve() {
	rep(i, 26) {
		char c = 'a' + i;
		bool exi = false;
		rep(j, 5)if (b[j] == c)exi = true;
		if (!exi)cc.push_back(c);
	}
	//cout << calc("baaa") << "\n";
	//cout << calc("tuat") << " " << calc("tuas") << "\n";
	int n; cin >> n;
	string s, t; cin >> s >> t;
	modint ans = calc(t);
	//cout << ans << "\n";
	bool isa = true;
	rep(i, s.size())if (s[i] != 'a')isa = false;
	if (!isa) {
		int las;
		per(i, n)if (s[i] != 'a') {
			las = i; break;
		}
		s[las]--;
		Rep(i, las + 1, n)s[i] = 'z';
		//cout << s << "\n";
		ans -= calc(s);
	}
	cout << ans << "\n";
}


signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	//cout << fixed << setprecision(8);
	//init_f();
	//init();
	//int t; cin >> t; rep(i, t)
	//expr();
	solve();
	return 0;
}
accuracy: 1
time_ms: 260
memory_kb: 4472
final_rank: 8

code_snippet: bool TEST = false;

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

#define rep(i,n) for(int (i)=0;(i)<(ll)(n);i++)
#define rrep(i,n) for(int (i)=(ll)(n)-1;(i)>=0;i--)
#define range(i,start,end,step) for(int (i)=start;(i)<(ll)(end);(i)+=(step))
#define rrange(i,start,end,step) for(int (i)=start;(i)>(ll)(end);(i)+=(step))

#define dump(x)  cerr << "Line " << __LINE__ << ": " <<  #x << " = " << (x) << "\n";
#define spa << " " <<
#define fi first
#define se second
#define all(a)  (a).begin(),(a).end()
#define allr(a)  (a).rbegin(),(a).rend()

using ld = long double;
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using pdd = pair<ld, ld>;
 
template<typename T> using V = vector<T>;
template<typename T> using VV = V<V<T>>;
template<typename T, typename T2> using P = pair<T, T2>;
template<typename T, typename T2> using M = map<T, T2>;
template<typename T> using S = set<T>;
template<typename T, typename T2> using UM = unordered_map<T, T2>;
template<typename T> using PQ = priority_queue<T, V<T>, greater<T>>;
template<typename T> using rPQ = priority_queue<T, V<T>, less<T>>;
template<typename T> vector<T> make_vec(size_t n, T a) { return vector<T>(n, a); }
template<typename... Ts> auto make_vec(size_t n, Ts... ts) { return vector<decltype(make_vec(ts...))>(n, make_vec(ts...)); }
template<class SS, class T> ostream& operator << (ostream& os, const pair<SS, T> v){os << "(" << v.first << ", " << v.second << ")"; return os;}
template<typename T> ostream& operator<<(ostream &os, const vector<T> &v) { for (auto &e : v) os << e << ' '; return os; }
template<class T> ostream& operator<<(ostream& os, const vector<vector<T>> &v){ for(auto &e : v){os << e << "\n";} return os;}
struct fast_ios { fast_ios(){ cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(20); }; } fast_ios_;
 
template <class T> void UNIQUE(vector<T> &x) {sort(all(x));x.erase(unique(all(x)), x.end());}
template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
void fail() { cout << -1 << '\n'; exit(0); }
inline int popcount(const int x) { return __builtin_popcount(x); }
inline int popcount(const ll x) { return __builtin_popcountll(x); }
template<typename T> void debug(vector<vector<T>>&v){for(ll i=0;i<v.size();i++)
{cerr<<v[i][0];for(ll j=1;j<v[i].size();j++)cerr spa v[i][j];cerr<<"\n";}};
template<typename T> void debug(vector<T>&v){if(v.size()!=0)cerr<<v[0];
for(ll i=1;i<v.size();i++)cerr spa v[i];
cerr<<"\n";};
template<typename T> P<T,T> divmod(T a, T b) {return make_pair(a/b, a%b);}

const ll INF = (1ll<<62);
// const ld EPS   = 1e-10;
// const ld PI    = acos(-1.0);

template< int mod >
struct ModInt {
  int x;

  ModInt() : x(0) {}

  ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}

  ModInt &operator+=(const ModInt &p) {
    if((x += p.x) >= mod) x -= mod;
    return *this;
  }

  ModInt &operator-=(const ModInt &p) {
    if((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }

  ModInt &operator*=(const ModInt &p) {
    x = (int) (1LL * x * p.x % mod);
    return *this;
  }

  ModInt &operator/=(const ModInt &p) {
    *this *= p.inverse();
    return *this;
  }

  ModInt operator-() const { return ModInt(-x); }

  ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }

  ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }

  ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }

  ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }

  bool operator==(const ModInt &p) const { return x == p.x; }

  bool operator!=(const ModInt &p) const { return x != p.x; }

  ModInt inverse() const {
    int a = x, b = mod, u = 1, v = 0, t;
    while(b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }

  ModInt pow(int64_t n) const {
    ModInt ret(1), mul(x);
    while(n > 0) {
      if(n & 1) ret *= mul;
      mul *= mul;
      n >>= 1;
    }
    return ret;
  }

  friend ostream &operator<<(ostream &os, const ModInt &p) {
    return os << p.x;
  }

  friend istream &operator>>(istream &is, ModInt &a) {
    int64_t t;
    is >> t;
    a = ModInt< mod >(t);
    return (is);
  }

  static int get_mod() { return mod; }
};

using m17 = ModInt<1'000'000'007>;
using m98 = ModInt<998'244'353>;
using MOD = m98;
ll mod = 998'244'353;
bool isv[26];
V<int> vs;
V<int> cs;

  
MOD sub(string s, bool less) {
  int n = s.size();
  V<int> ss(n,0);
  rep(i,n) ss[i] = s[i] - 'a';
  MOD dp[2][4][26][26];
  rep(b,2) rep(t,4) rep(c,26) rep(c2,26) dp[b][t][c][c2] = 0;
  rep(c,26) {
    bool nb;
    if (isv[c]) continue;
    if (c>ss[0]) continue;
    if (c<ss[0]) nb = 1;
    else nb = 0;
    dp[nb][0][c][c] = 1;
  }
  // rep(b,2) {rep(t,4) {rep(c,26) {cout << dp[b][t][c] << " ";} cout << endl;} cout << endl;}
  auto nx = [&ss, n] (bool b, int t, int c, int c2, int nc, int i) {
    bool nb;
    int nt;
    int nc2=c2;
    if (t==0) {
      if (nc==c) {
        nt = t;
      } else {
        if (isv[nc]) nt = 1;
        else nt = -1;
      }
    } else if (t==1) {
      if (nc==c) nt = 1;
      else if (isv[nc]) nt = 2;
      else nt = -1;
    } else if (t==2) {
      if (nc==c) nt = 2;
      else if (isv[nc]) nt = -1;
      else if (nc==c2) {
        nt = 3;
        nc2 = 0;
      } else nt = -1;
    } else if (t==3) {
      if (nc==c) nt = 3;
      else nt = -1;
    }
    if (b) nb = 1;
    else if (nc<ss[i]) nb = 1;
    else if (nc>ss[i]) nt = -1;
    else nb = 0;
    tuple<bool, int, int> p = make_tuple(nb,nt,nc2);
    return p;
  };
  range(i, 1, n, 1) {
    MOD ndp[2][4][26][26];
    rep(b,2) rep(t,4) rep(c,26) rep(c2,26) ndp[b][t][c][c2] = 0;
    rep(b,2) rep(t,4) rep(c,26) rep(c2,26) {
      auto val = dp[b][t][c][c2];
      if (val==0) continue;
      rep(nc, 26) {
        auto [nb, nt, nc2] = nx(b, t, c, c2, nc, i);
        if (nt==-1) continue;
        ndp[nb][nt][nc][nc2] += val;
      }
    }
    rep(b,2) rep(t,4) rep(c,26) rep(c2,26) dp[b][t][c][c2] = ndp[b][t][c][c2];
    // cout << i spa ss[i] << endl;
    // rep(b,2) {rep(t,4) {rep(c,26) rep(c2,26) {cout << dp[b][t][c][c2] << " ";} cout << endl;} cout << endl;}
  }
  MOD ans = 0;
  if (!less) rep(b,2) rep(c,26) rep(c2,26) ans += dp[b][3][c][c2];
  else rep(c,26) rep(c2,26) ans += dp[1][3][c][c2];
  return ans;
}
void Main(){
    ll n;
    cin >> n;
    string s,t;
    isv['a'-'a'] = 1;
    isv['i'-'a'] = 1;
    isv['u'-'a'] = 1;
    isv['e'-'a'] = 1;
    isv['o'-'a'] = 1;
    rep(i,26) if (isv[i]) vs.push_back(i); else cs.push_back(i);

    cin >> s >> t;
    MOD ans = sub(t, 0) - sub(s, 1);
    // chmax(ans, 0);
    cout << ans << endl;
}

int main(void){
    std::ifstream in("tmp_in");
    if (TEST) {
        std::cin.rdbuf(in.rdbuf());
        std::cout << std::fixed << std::setprecision(15);
    } else {
        std::cin.tie(nullptr);
        std::ios_base::sync_with_stdio(false);
        std::cout << std::fixed << std::setprecision(15);
    }
    Main();
}
accuracy: 1
time_ms: 270
memory_kb: 3508
final_rank: 9

code_snippet: #include <bits/stdc++.h>
//#include<atcoder/all>
using namespace std;
//using namespace atcoder;
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++)

ll mod = 1e9 + 7;


int main() {
	ll N;
	cin >> N;
	string S, T;
	cin >> S >> T;
	ll mod = 998244353;
	ll an = 0;
	string siin = "qwrtypsdfghjklzxcvbnm";
	string boin = "aiueo";
	rep(s, 21) {//1,4文字目
		char P = siin[s];
		rep(b, 5) {//2文字目
			char B = boin[b];
			rep(c, 5) {//3文字目
				char C = boin[c];
				if (P == 'w' && B == 'a' && C == 'i') {
					cout << "";
				}
				if (b == c)continue;
				vector<vll> DPSJ(N + 1, vll(5, 0));
				vector<vll> DPTJ(N + 1, vll(5, 0));
				vector<vll> DPT(N + 1, vll(5, 0));
				vector<vll> DPS(N + 1, vll(5, 0));
				DPTJ[0][0] = 1;
				DPSJ[0][0] = 1;
				rep(i, N) {
					DPT[i + 1][1] += DPT[i][1] + DPT[i][0];
					DPS[i + 1][4] += DPS[i][4] + DPS[i][3];
					DPT[i + 1][4] += DPT[i][4] + DPT[i][3];
					DPS[i + 1][1] += DPS[i][1] + DPS[i][0];
					if (S[i] < P) {
						DPS[i + 1][1] += DPSJ[i][0] + DPSJ[i][1];
						DPS[i + 1][4] += DPSJ[i][3] + DPSJ[i][4];
					}
					else if (S[i] == P) {
						DPSJ[i + 1][1] += DPSJ[i][1] + DPSJ[i][0];
						DPSJ[i + 1][4] += DPSJ[i][4] + DPSJ[i][3];


					}

					if (T[i] < P) {
						DPT[i + 1][1] += DPTJ[i][0] + DPTJ[i][1];
						DPT[i + 1][4] += DPTJ[i][3] + DPTJ[i][4];
					}
					else if (T[i] == P) {
						DPTJ[i + 1][1] += DPTJ[i][1] + DPTJ[i][0];
						DPTJ[i + 1][4] += DPTJ[i][4] + DPTJ[i][3];

					}

					DPSJ[i + 1][1] %= mod;
					DPTJ[i + 1][4] %= mod;
					DPSJ[i + 1][4] %= mod;
					DPTJ[i + 1][1] %= mod;
					DPS[i + 1][1] %= mod;
					DPS[i + 1][4] %= mod;
					DPT[i + 1][1] %= mod;
					DPT[i + 1][4] %= mod;

					DPS[i + 1][2] += DPS[i][2] + DPS[i][1];
					DPT[i + 1][2] += DPT[i][2] + DPT[i][1];
					if (S[i] < B) {
						DPS[i + 1][2] += DPSJ[i][1] + DPSJ[i][2];

					}
					else if (S[i] == B) {
						DPSJ[i + 1][2] += DPSJ[i][1] + DPSJ[i][2];

					}

					if (T[i] < B) {
						DPT[i + 1][2] += DPTJ[i][1] + DPTJ[i][2];

					}
					else if (T[i] == B) {
						DPTJ[i + 1][2] += DPTJ[i][1] + DPTJ[i][2];

					}

					DPSJ[i + 1][2] %= mod;
					DPTJ[i + 1][2] %= mod;
					DPS[i + 1][2] %= mod;
					DPT[i + 1][2] %= mod;

					DPS[i + 1][3] += DPS[i][3] + DPS[i][2];
					DPT[i + 1][3] += DPT[i][3] + DPT[i][2];
					if (S[i] < C) {
						DPS[i + 1][3] += DPSJ[i][2] + DPSJ[i][3];

					}
					else if (S[i] == C) {
						DPSJ[i + 1][3] += DPSJ[i][3] + DPSJ[i][2];

					}

					if (T[i] < C) {
						DPT[i + 1][3] += DPTJ[i][2] + DPTJ[i][3];

					}
					else if (T[i] == C) {
						DPTJ[i + 1][3] += DPTJ[i][3] + DPTJ[i][2];

					}

					DPSJ[i + 1][3] %= mod;
					DPTJ[i + 1][3] %= mod;
					DPS[i + 1][3] %= mod;
					DPT[i + 1][3] %= mod;




				}
				if (DPS[N][4] + DPSJ[N][4] - DPT[N][4] >= 1) {
					//cout << P << B << C << P << endl;
				}
				an += max(DPS[N][4] + DPSJ[N][4] - DPT[N][4],0ll);
				an %= mod;
			}
		}

	}
	cout << an << endl;

}
accuracy: 1
time_ms: 550
memory_kb: 6052
final_rank: 15

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

using namespace std;

using int64 = long long;

// const int mod = 1e9 + 7;
const int mod = 998244353;

const int64 infll = (1LL << 62) - 1;
const int inf = (1 << 30) - 1;

struct IoSetup {
  IoSetup() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
    cerr << fixed << setprecision(10);
  }
} iosetup;


template< typename T1, typename T2 >
ostream &operator<<(ostream &os, const 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 >
ostream &operator<<(ostream &os, const vector< T > &v) {
  for(int i = 0; i < (int) 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 >
inline bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }

template< typename T1, typename T2 >
inline bool chmin(T1 &a, T2 b) { return a > b && (a = b, true); }

template< typename T = int64 >
vector< T > make_v(size_t a) {
  return vector< T >(a);
}

template< typename T, typename... Ts >
auto make_v(size_t a, Ts... ts) {
  return vector< decltype(make_v< T >(ts...)) >(a, make_v< T >(ts...));
}

template< typename T, typename V >
typename enable_if< is_class< T >::value == 0 >::type fill_v(T &t, const V &v) {
  t = v;
}

template< typename T, typename V >
typename enable_if< is_class< T >::value != 0 >::type fill_v(T &t, const V &v) {
  for(auto &e: t) fill_v(e, v);
}

template< typename F >
struct FixPoint : F {
  FixPoint(F &&f) : F(forward< F >(f)) {}

  template< typename... Args >
  decltype(auto) operator()(Args &&... args) const {
    return F::operator()(*this, forward< Args >(args)...);
  }
};

template< typename F >
inline decltype(auto) MFP(F &&f) {
  return FixPoint< F >{forward< F >(f)};
}

/**
 * @brief Montgomery ModInt
 */
template< uint32_t mod, bool fast = false >
struct MontgomeryModInt {
  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;

  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.inverse();
    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 get() 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 inverse() const {
    return pow(mod - 2);
  }

  friend ostream &operator<<(ostream &os, const mint &p) {
    return os << p.get();
  }

  friend istream &operator>>(istream &is, mint &a) {
    i64 t;
    is >> t;
    a = mint(t);
    return is;
  }

  static u32 get_mod() { return mod; }
};

using modint = MontgomeryModInt< mod >;

int main() {
  int N;
  cin >> N;
  string S, T;
  cin >> S >> T;

  auto solve = [](string s, bool eq) -> modint {
    int n = (int) s.size();
    // 0はp
    // 1はq
    // 2はr
    // 3はp
    vector< int > mp(256);
    mp['a'] = mp['i'] = mp['u'] = mp['e'] = mp['o'] = 1;
    const string io = "aiueo";
    auto dp = make_v< int >(n, 4, 2, 26, 5);
    fill_v(dp, -1);
    auto rec = MFP([&](auto rec, int idx, int olphe, bool strict, char p, char q) -> int {
      if(idx == n) {
        if(olphe != 3) return 0;
        if(strict & not eq) return 0;
        return 1;
      }
      if(~dp[idx][olphe][strict][p - 'a'][q]) {
        return dp[idx][olphe][strict][p - 'a'][q];
      }
      int64 ret = 0;
      if(olphe == 0) {
        // use p
        if(strict && s[idx] < p) return 0;
        ret += rec(idx + 1, 0, strict & (s[idx] == p), p, q);
        if(idx + 1 < n) {
          ret += rec(idx + 1, 1, strict & (s[idx] == p), p, q);
        }
      } else if(olphe == 1) {
        // use io[q]
        if(strict && s[idx] < io[q]) return 0;
        ret += rec(idx + 1, 1, strict & (s[idx] == io[q]), p, q);
        if(idx + 1 < n) {
          for(int i = 0; i < 5; i++) {
            if(i != q) ret += rec(idx + 1, 2, strict & (s[idx] == io[q]), p, i);
          }
        }
      } else if(olphe == 2) {
        // use io[q]
        if(strict && s[idx] < io[q]) return 0;
        ret += rec(idx + 1, 2, strict & (s[idx] == io[q]), p, q);
        if(idx + 1 < n) {
          ret += rec(idx + 1, 3, strict & (s[idx] == io[q]), p, q);
        }
      } else { // olphe == 3
        // use p
        if(strict && s[idx] < p) return 0;
        ret += rec(idx + 1, 3, strict & (s[idx] == p), p, q);
      }
      ret %= mod;
      return dp[idx][olphe][strict][p - 'a'][q] = ret;
    });
    modint ret = 0;
    for(char p = 'a'; p <= 'z'; p++) {
      if(mp[p]) continue;
      for(int i = 0; i < 5; i++) ret += rec(0, 0, true, p, i);
    }
    return ret;
  };
  modint ret = 0;
  ret += solve(T, true);
  ret -= solve(S, false);
  cout << ret << "\n";
}
accuracy: 1
time_ms: 790
memory_kb: 123348
final_rank: 19

code_snippet: #pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#include <unistd.h>
using namespace std;
#if __has_include(<atcoder/all>)
#include <atcoder/all>
using namespace atcoder;
#endif
using ll = long long;
using ld = long double;
using ull = unsigned long long;
#define endl "\n"
typedef pair<int, int> Pii;
#define REP(i, n) for (int i = 0; i < (n); ++i)
#define REP3(i, m, n) for (int i = (m); (i) < int(n); ++ (i))
#define FOR(i,a,b) for(ll i=a;i<=(ll)(b);i++)
#define rep(i,a,b) for(int i=(int)(a);i<(int)(b);i++)
#define ALL(x) begin(x), end(x)
#define all(s) (s).begin(),(s).end()
//#define rep2(i, m, n) for (int i = (m); i < (n); ++i)
//#define rep(i, n) rep2(i, 0, n)
#define PB push_back 
#define drep2(i, m, n) for (int i = (m)-1; i >= (n); --i)
#define drep(i, n) drep2(i, n, 0)
#define rever(vec) reverse(vec.begin(), vec.end())
#define sor(vec) sort(vec.begin(), vec.end())
//#define FOR(i,a,b) for(ll i=a;i<=(ll)(b);i++)
#define fi first
#define se second
#define pb push_back
#define P pair<ll,ll>
#define PQminll priority_queue<ll, vector<ll>, greater<ll>>
#define PQmaxll priority_queue<ll,vector<ll>,less<ll>>
#define PQminP priority_queue<P, vector<P>, greater<P>>
#define PQmaxP priority_queue<P,vector<P>,less<P>>
#define NP next_permutation
//const ll mod = 1000000009;
const ll mod = 998244353;
//const ll mod = 1000000007;
const ll inf = 4100000000000000000ll;
const ld eps = ld(0.00000000001);
//static const long double pi = 3.141592653589793;
template<class T>void vcin(vector<T> &n){for(int i=0;i<int(n.size());i++) cin>>n[i];}
template<class T,class K>void vcin(vector<T> &n,vector<K> &m){for(int i=0;i<int(n.size());i++) cin>>n[i]>>m[i];}
template<class T>void vcout(vector<T> &n){for(int i=0;i<int(n.size());i++){cout<<n[i]<<" ";}cout<<endl;}
template<class T>void vcin(vector<vector<T>> &n){for(int i=0;i<int(n.size());i++){for(int j=0;j<int(n[i].size());j++){cin>>n[i][j];}}}
template<class T>void vcout(vector<vector<T>> &n){for(int i=0;i<int(n.size());i++){for(int j=0;j<int(n[i].size());j++){cout<<n[i][j]<<" ";}cout<<endl;}cout<<endl;}
void yes(bool a){cout<<(a?"yes":"no")<<endl;}
void YES(bool a){cout<<(a?"YES":"NO")<<endl;}
void Yes(bool a){cout<<(a?"Yes":"No")<<endl;}
void possible(bool a){ cout<<(a?"possible":"impossible")<<endl; }
void Possible(bool a){ cout<<(a?"Possible":"Impossible")<<endl; }
void POSSIBLE(bool a){ cout<<(a?"POSSIBLE":"IMPOSSIBLE")<<endl; }
template<class T>auto min(const T& a){ return *min_element(all(a)); }
template<class T>auto max(const T& a){ return *max_element(all(a)); }
template<class T,class F>void print(pair<T,F> a){cout<<a.fi<<" "<<a.se<<endl;}
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0;}
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0;}
template<class T> void ifmin(T t,T u){if(t>u){cout<<-1<<endl;}else{cout<<t<<endl;}}
template<class T> void ifmax(T t,T u){if(t>u){cout<<-1<<endl;}else{cout<<t<<endl;}}
template<typename T,typename ...Args>auto make_vector(T x,int arg,Args ...args){if constexpr(sizeof...(args)==0)return vector<T>(arg,x);else return vector(arg,make_vector<T>(x,args...));}
ll fastgcd(ll u,ll v){ll shl=0;while(u&&v&&u!=v){bool eu=!(u&1);bool ev=!(v&1);if(eu&&ev){++shl;u>>=1;v>>=1;}else if(eu&&!ev){u>>=1;}else if(!eu&&ev){v>>=1;}else if(u>=v){u=(u-v)>>1;}else{ll tmp=u;u=(v-u)>>1;v=tmp;}}return !u?v<<shl:u<<shl;}
ll modPow(ll a, ll n, ll mod) { if(mod==1) return 0;ll ret = 1; ll p = a % mod; while (n) { if (n & 1) ret = ret * p % mod; p = p * p % mod; n >>= 1; } return ret; }
vector<ll> divisor(ll x){ vector<ll> ans; for(ll i = 1; i * i <= x; i++){ if(x % i == 0) {ans.push_back(i); if(i*i!=x){ ans.push_back(x / ans[i]);}}}sor(ans); return ans; }
ll pop(ll x){return __builtin_popcountll(x);}
ll poplong(ll x){ll y=-1;while(x){x/=2;y++;}return y;}
template<class T>
struct Sum{
  vector<T> data;
  Sum(const vector<T>& v):data(v.size()+1){
    for(ll i=0;i<v.size();i++) data[i+1]=data[i]+v[i];
  }
  T get(ll l,ll r) const {
    return data[r]-data[l];
  }
};
template<class T>
struct Sum2{
  vector<vector<T>> data;
  Sum2(const vector<vector<T>> &v):data(v.size()+1,vector<T>(v[0].size()+1)){
    for(int i=0;i<v.size();i++) for(int j=0;j<v[i].size();j++) data[i+1][j+1]=data[i][j+1]+v[i][j];
    for(int i=0;i<v.size();i++) for(int j=0;j<v[i].size();j++) data[i+1][j+1]+=data[i+1][j];
  }
  T get(ll x1,ll y1,ll x2,ll y2) const {
    return data[x2][y2]+data[x1][y1]-data[x1][y2]-data[x2][y1];
  }
};

void cincout(){
  ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
  cout<< fixed << setprecision(10);
}
ll solve(ll p,ll q,ll r,vector<ll> &a,vector<ll> &b){
  vector<vector<vector<ll>>> dp(2,vector<vector<ll>>(2,vector<ll>(4)));
  auto dp2=dp;
  for(int i=0;i<2;i++){
    for(int j=0;j<2;j++){
      for(int k=0;k<4;k++) dp[i][j][k]=0;
    }
  }
  ll n=a.size();
  if(a[0]==p&&p==b[0]){
    dp[0][0][0]=1;
  }
  else if(a[0]==p){
    dp[0][1][0]=1;
  }
  else if(b[0]==p){
    dp[1][0][0]=1;
  }
  else if(a[0]<p&&p<b[0]){
    dp[1][1][0]=1;
  }
  vector<ll> in={p,q,r,p};
  for(int i=1;i<n;i++){

    for(int j=0;j<2;j++){
      for(int k=0;k<2;k++){
        for(int h=0;h<4;h++){
          dp2[j][k][h]=0;
        //  cout<<i<<" "<<j<<" "<<k<<" "<<h<<" "<<dp[j][k][h]<<endl;
        }
      }
    }
    for(int j=0;j<2;j++){
      for(int k=0;k<2;k++){
        for(int h=0;h<4;h++){
          if(j==1&&k==1){
            if(h+1<4){
              (dp2[j][k][h+1]+=dp[j][k][h])%=mod;
            }
            (dp2[j][k][h]+=dp[j][k][h])%=mod;
          }
          if(j==1&&k==0){
            if(h==0){
              if(p<b[i]) (dp2[1][1][0]+=dp[j][k][h])%=mod;
              if(p==b[i]) (dp2[1][0][0]+=dp[j][k][h])%=mod;
              if(q==b[i]) (dp2[1][0][1]+=dp[j][k][h])%=mod;
              if(q<b[i]) (dp2[1][1][1]+=dp[j][k][h])%=mod;
            }
            if(h==1){
              if(q==b[i]) (dp2[1][0][1]+=dp[j][k][h])%=mod;
              if(q<b[i]) (dp2[1][1][1]+=dp[j][k][h])%=mod;
              if(r==b[i]) (dp2[1][0][2]+=dp[j][k][h])%=mod;
              if(r<b[i]) (dp2[1][1][2]+=dp[j][k][h])%=mod;
            }
            if(h==2){
              if(r==b[i]) (dp2[1][0][2]+=dp[j][k][h])%=mod;
              if(r<b[i]) (dp2[1][1][2]+=dp[j][k][h])%=mod;
              if(p<b[i]) (dp2[1][1][3]+=dp[j][k][h])%=mod;
              if(p==b[i]) (dp2[1][0][3]+=dp[j][k][h])%=mod;
            }
            if(h==3){
              if(p<b[i]) (dp2[1][1][3]+=dp[j][k][h])%=mod;
              if(p==b[i]) (dp2[1][0][3]+=dp[j][k][h])%=mod;
            }
          }
          if(j==0&&k==1){
            if(h==0){
              if(p>a[i]) (dp2[1][1][0]+=dp[j][k][h])%=mod;
              if(p==a[i]) (dp2[0][1][0]+=dp[j][k][h])%=mod;
              if(q==a[i]) (dp2[0][1][1]+=dp[j][k][h])%=mod;
              if(q>a[i]) (dp2[1][1][1]+=dp[j][k][h])%=mod;
            }
            if(h==1){
              if(q==a[i]) (dp2[0][1][1]+=dp[j][k][h])%=mod;
              if(q>a[i]) (dp2[1][1][1]+=dp[j][k][h])%=mod;
              if(r==a[i]) (dp2[0][1][2]+=dp[j][k][h])%=mod;
              if(r>a[i]) (dp2[1][1][2]+=dp[j][k][h])%=mod;
            }
            if(h==2){
              if(r==a[i]) (dp2[0][1][2]+=dp[j][k][h])%=mod;
              if(r>a[i]) (dp2[1][1][2]+=dp[j][k][h])%=mod;
              if(p>a[i]) (dp2[1][1][3]+=dp[j][k][h])%=mod;
              if(p==a[i]) (dp2[0][1][3]+=dp[j][k][h])%=mod;
            }
            if(h==3){
              if(p>a[i]) (dp2[1][1][3]+=dp[j][k][h])%=mod;
              if(p==a[i]) (dp2[0][1][3]+=dp[j][k][h])%=mod;
            }
          }
          if(j==0&&k==0){
            if(h==0){
              if(p==a[i]&&p==b[i]) (dp2[0][0][0]+=dp[j][k][h])%=mod;
              if(p>a[i]&&p==b[i]) (dp2[1][0][0]+=dp[j][k][h])%=mod;
              if(p==a[i]&&p<b[i]) (dp2[0][1][0]+=dp[j][k][h])%=mod;
              if(p>a[i]&&p<b[i]) (dp2[1][1][0]+=dp[j][k][h])%=mod;
              if(q==a[i]&&q==b[i]) (dp2[0][0][1]+=dp[j][k][h])%=mod;
              if(q>a[i]&&q==b[i]) (dp2[1][0][1]+=dp[j][k][h])%=mod;
              if(q==a[i]&&q<b[i]) (dp2[0][1][1]+=dp[j][k][h])%=mod;
              if(q>a[i]&&q<b[i]) (dp2[1][1][1]+=dp[j][k][h])%=mod;
            }
            if(h==1){
              if(q==a[i]&&q==b[i]) (dp2[0][0][1]+=dp[j][k][h])%=mod;
              if(q>a[i]&&q==b[i]) (dp2[1][0][1]+=dp[j][k][h])%=mod;
              if(q==a[i]&&q<b[i]) (dp2[0][1][1]+=dp[j][k][h])%=mod;
              if(q>a[i]&&q<b[i]) (dp2[1][1][1]+=dp[j][k][h])%=mod;
              if(r==a[i]&&r==b[i]) (dp2[0][0][2]+=dp[j][k][h])%=mod;
              if(r>a[i]&&r==b[i]) (dp2[1][0][2]+=dp[j][k][h])%=mod;
              if(r==a[i]&&r<b[i]) (dp2[0][1][2]+=dp[j][k][h])%=mod;
              if(r>a[i]&&r<b[i]) (dp2[1][1][2]+=dp[j][k][h])%=mod;
            }
            if(h==2){
              if(r==a[i]&&r==b[i]) (dp2[0][0][2]+=dp[j][k][h])%=mod;
              if(r>a[i]&&r==b[i]) (dp2[1][0][2]+=dp[j][k][h])%=mod;
              if(r==a[i]&&r<b[i]) (dp2[0][1][2]+=dp[j][k][h])%=mod;
              if(r>a[i]&&r<b[i]) (dp2[1][1][2]+=dp[j][k][h])%=mod;
              if(p==a[i]&&p==b[i]) (dp2[0][0][3]+=dp[j][k][h])%=mod;
              if(p>a[i]&&p==b[i]) (dp2[1][0][3]+=dp[j][k][h])%=mod;
              if(p==a[i]&&p<b[i]) (dp2[0][1][3]+=dp[j][k][h])%=mod;
              if(p>a[i]&&p<b[i]) (dp2[1][1][3]+=dp[j][k][h])%=mod;
            }
            if(h==3){
              if(p==a[i]&&p==b[i]) (dp2[0][0][3]+=dp[j][k][h])%=mod;
              if(p>a[i]&&p==b[i]) (dp2[1][0][3]+=dp[j][k][h])%=mod;
              if(p==a[i]&&p<b[i]) (dp2[0][1][3]+=dp[j][k][h])%=mod;
              if(p>a[i]&&p<b[i]) (dp2[1][1][3]+=dp[j][k][h])%=mod;
            }
          }
        }
      }
    }
    dp=dp2;
  }
  //cout<<p<<" "<<q<<" "<<r<<" "<<dp[1][1][3]<<endl;
  return dp[1][1][3]+dp[0][1][3]+dp[1][0][3]+dp[0][0][3];
}
int main() {
  cincout();
  ll n;
  cin>>n;
  string s,t;
  cin>>s>>t;
  vector<ll> a,b;
  for(int i=0;i<n;i++){
    a.pb(s[i]-'a');
    b.pb(t[i]-'a');
  } 
  for(int i=0;i<n;i++){
    if(a[i]>b[i]){
      cout<<0<<endl;
      return 0;
    }
    if(a[i]<b[i]) break;
  }
  vector<int> si,bo;
  for(int i=0;i<26;i++){
    char x=char(int('a')+i);
    if(x=='a'||x=='i'||x=='u'||x=='e'||x=='o') si.pb(i);
    else bo.pb(i);
  }
  ll ans=0;
  for(int i=0;i<21;i++){
    for(int j=0;j<5;j++){
      for(int k=0;k<5;k++){
        if(j==k) continue;
        (ans+=solve(bo[i],si[j],si[k],a,b))%=mod;
      }
    }
  }
  cout<<ans<<endl;
}
accuracy: 1
time_ms: 360
memory_kb: 3644
final_rank: 11

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

#define REP(i,n) for(int i=0;i<(n);i++)
#define RREP(i,n) for(int i=(n-1);i>=0;i--)
#define ALL(v) v.begin(),v.end()

using ll=long long;
const ll MOD=998244353;

ll dp[10000][252][2][2];
string siin="bcdfghjklmnpqrstvwxyz";
string boin="aiueo";
void ADD(ll &a,ll b){
  a+=b;
  if(a>=MOD)a-=MOD;
}

int main(){
  int n;cin>>n;
  string s,t;cin>>s>>t;
  if(s>t){
    cout<<0<<endl;
    return 0;
  }
  REP(i,21){
    int p=siin[i];
    if(s[0]<=p&&p<=t[0])
      dp[0][i][s[0]<p][p<t[0]]=1;
  }
  for(int i=1;i<n;i++){
    REP(state,251)REP(S,2)REP(T,2){
      if(!dp[i-1][state][S][T])continue;
      //cout<<i<<" "<<state<<" "<<S<<" "<<T<<" "<<dp[i-1][state][S][T]<<endl;
      if(state<21){
        char p=siin[state];
        if((S||s[i]<=p)&&(T||p<=t[i]))
          ADD(dp[i][state][S|s[i]<p][T|p<t[i]],dp[i-1][state][S][T]);
        REP(qi,5){
          char q=boin[qi];
          if((S||s[i]<=q)&&(T||q<=t[i]))
            ADD(dp[i][21+state*5+qi][S|s[i]<q][T|q<t[i]],dp[i-1][state][S][T]);
        }
      }
      else if(state<21+105){
        int pi=(state-21)/5;
        char p=siin[pi];
        char q=boin[(state-21)%5];

        if((S||s[i]<=q)&&(T||q<=t[i]))
          ADD(dp[i][state][S|s[i]<q][T|q<t[i]],dp[i-1][state][S][T]);
        REP(ri,5){
          char r=boin[ri];
          if(r!=q&&(S||s[i]<=r)&&(T||r<=t[i]))
            ADD(dp[i][21+5*21+pi*5+ri][S|s[i]<r][T|r<t[i]],dp[i-1][state][S][T]);
        }
      }
      else if(state<21+105+105){
        int pi=(state-21-105)/5;
        char p=siin[pi];
        char r=boin[(state-21-105)%5];

        if((S||s[i]<=r)&&(T||r<=t[i]))
          ADD(dp[i][state][S|s[i]<r][T|r<t[i]],dp[i-1][state][S][T]);
        
        if((S||s[i]<=p)&&(T||p<=t[i]))
          ADD(dp[i][21+5*21+5*21+pi][S|s[i]<p][T|p<t[i]],dp[i-1][state][S][T]);
      }
      else{
        int pi=state-21-105-105;
        char p=siin[pi];
        if((S||s[i]<=p)&&(T||p<=t[i]))
          ADD(dp[i][state][S|s[i]<p][T|p<t[i]],dp[i-1][state][S][T]);
      }
    }
  }
  ll ans=0;
  for(int state=21+105+105;state<21+105+105+21;state++)REP(S,2)REP(T,2)
    ADD(ans,dp[n-1][state][S][T]);
  cout<<ans<<endl;
}
accuracy: 1
time_ms: 30
memory_kb: 80604
final_rank: 13

code_snippet: #pragma region templates
//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
using db = double;
using ld = long double;
template <typename T> using V = vector<T>;
template <typename T> using VV = vector<vector<T>>;
template <typename T> using PQ = priority_queue<T>;
template <typename T> using PQR = priority_queue<T, vector<T>, greater<T>>;
#define fs first
#define sc second
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define eb emplace_back
#define lb(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define ub(c, x) distance((c).begin(), upper_bound(all(c), (x)))
#define all(v) (v).begin(), (v).end()
#define siz(v) (ll)(v).size()
#define rep(i, a, n) for (ll i = a; i < (ll)(n); ++i)
#define repr(i, a, n) for (ll i = n - 1; (ll)a <= i; --i)
#define pw2(n) (1ll << (n))
#define pcntl(x) __builtin_popcountll(x)
#define ENDL '\n'
typedef pair<int, int> Pi;
typedef pair<ll, ll> PL;
constexpr ll mod = 998244353;
constexpr ll INF = 1000000099;
constexpr ll LINF = (ll)(1e18 + 99);
const ld PI = acos((ld)-1);
constexpr ll dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
template <typename T, typename U> inline bool chmin(T &t, const U &u) {
  if (t > u) {
    t = u;
    return 1;
  }
  return 0;
}
template <typename T, typename U> inline bool chmax(T &t, const U &u) {
  if (t < u) {
    t = u;
    return 1;
  }
  return 0;
}
template <typename T> inline T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
inline void Yes() { cout << "Yes" << ENDL; }
inline void No() { cout << "No" << ENDL; }
inline void YES() { cout << "YES" << ENDL; }
inline void NO() { cout << "NO" << ENDL; }

template <typename T, typename Y> inline T mpow(T a, Y n) {
  T res = 1;
  for (; n; n >>= 1) {
    if (n & 1)
      res = res * a;
    a = a * a;
  }
  return res;
}

template <typename T> vector<T> finddivisor(T x) { //整数xの約数(xを含む)
  vector<T> divisor;
  for (T i = 1; (i * i) <= x; i++) {
    if (x % i == 0) {
      divisor.push_back(i);
      if (i * i != x) {
        divisor.push_back(x / i);
      }
    }
  }
  sort(divisor.begin(), divisor.end());
  return divisor;
}

template <typename T> V<T> prefix_sum(const V<T> &v) {
  int n = v.size();
  V<T> ret(n + 1);
  rep(i, 0, n) ret[i + 1] = ret[i] + v[i];
  return ret;
}

template <typename T> void get_unique(V<T> &v) {
  sort(all(v));
  v.erase(unique(all(v)), v.end());
  return;
}

template <typename T> T rand(T l, T r) {
  static random_device rd;
  static mt19937 g(rd());
  return uniform_int_distribution<T>(l, r)(g);
} //[]

template <typename T> istream &operator>>(istream &is, vector<T> &vec) {
  for (auto &&x : vec)
    is >> x;
  return is;
}

template <typename T, typename Y>
ostream &operator<<(ostream &os, const pair<T, Y> &p) {
  return os << "{" << p.fs << "," << p.sc << "}";
}

template <typename T> ostream &operator<<(ostream &os, const V<T> &v) {
  os << "{";
  for (auto e : v)
    os << e << ",";
  return os << "}";
}

#ifdef LOCAL
template <typename... Args> void debug(Args &...args) {
  for (auto const &x : {args...}) {
    cerr << x << ' ';
  }
  cerr << ENDL;
}
#else
template <typename... Args> void debug(Args &...args) { return; }
#endif
#pragma endregion templates

template <const long long MOD = mod> // MODを適宜設定すること
struct Mint {
  using M = Mint;
  ll a;
  Mint(ll x = 0) {
    a = x % MOD;
    if (a < 0)
      a += MOD;
  } // Mintで

  M pow(ll n) {
    assert(n >= 0);
    M b = *this, r = 1 % MOD;
    while (n) {
      if (n & 1)
        r *= b;
      b *= b;
      n >>= 1;
    }
    return r;
  }

  M inv() { return pow(MOD - 2); }

  M &operator+=(M r) {
    a += r.a;
    if (a >= MOD)
      a -= MOD;
    return *this;
  }
  M &operator-=(M r) {
    a += MOD - r.a;
    if (a >= MOD)
      a -= MOD;
    return *this;
  }
  M &operator*=(M r) {
    a = 1LL * a * r.a % MOD;
    return *this;
  }
  M &operator/=(M r) { return (*this) *= r.inv(); }
  M operator+(M r) const { return M(a) += r; };
  M operator-(M r) const { return M(a) -= r; };
  M operator*(M r) const { return M(a) *= r; };
  M operator/(M r) const { return M(a) /= r; };
  M operator-() const { return M() - *this; }

  friend ostream &operator<<(ostream &os, const M &r) { return os << r.a; }
};
using M = Mint<mod>;

M dp[10010][4][2][2] = {};

signed main() {
  cin.tie(0);
  cerr.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(20);
  V<char> v(0), c(0);
  for (char i = 'a'; i <= 'z'; ++i) {
    if (i == 'a' || i == 'i' || i == 'u' || i == 'e' || i == 'o') {
      v.eb(i);
    } else {
      c.eb(i);
    }
  }

  ll n;
  cin >> n;
  string s, t;
  cin >> s >> t;
  M ans = 0;

  for (auto &&p : c) {
    for (auto &&q : v) {
      for (auto &&r : v)
        if (q != r) {
          V<char> tuat = {p, q, r, p};
          rep(i, 0, n + 1) rep(j, 0, 4) rep(k, 0, 2) rep(l, 0, 2)
              dp[i][j][k][l] = 0;
          dp[0][0][0][0] = 1;

          rep(i, 0, n) {

            rep(j, 0, 4) {
              char nex = tuat[j];
              int sf = 1, tf = 1;

              if (s[i] == nex)
                sf = 0;
              else if (nex < s[i])
                sf = -1;

              if (t[i] == nex)
                tf = 0;
              else if (t[i] < nex)
                tf = -1;

              if (sf >= 0 && tf >= 0) {
                dp[i + 1][j][sf][tf] += dp[i][j][0][0];
                if (j < 3 && i + 1 != n)
                  dp[i + 1][j + 1][sf][tf] += dp[i][j][0][0];
              }

              if (tf >= 0) {
                dp[i + 1][j][1][tf] += dp[i][j][1][0];
                if (j < 3 && i + 1 != n)
                  dp[i + 1][j + 1][1][tf] += dp[i][j][1][0];
              }

              if (sf >= 0) {
                dp[i + 1][j][sf][1] += dp[i][j][0][1];
                if (j < 3 && i + 1 != n)
                  dp[i + 1][j + 1][sf][1] += dp[i][j][0][1];
              }

              dp[i + 1][j][1][1] += dp[i][j][1][1];
              if (j < 3 && i + 1 != n)
                dp[i + 1][j + 1][1][1] += dp[i][j][1][1];
            }
          }
          ans +=
              dp[n][3][0][0] + dp[n][3][0][1] + dp[n][3][1][0] + dp[n][3][1][1];
        }
    }
  }
  cout << ans << ENDL;
}
//(・_・)(・_・)(・_・)(・_・)
// CHECK overflow,what to output?
// any other simpler approach?
accuracy: 1
time_ms: 110
memory_kb: 4736
final_rank: 1