from collections.abc import Iterable def accum_dp(xs: Iterable, f, op, e, init: dict, *, is_reset=True): dp = init.copy() for x in xs: pp = {} if is_reset else dp.copy() dp, pp = pp, dp for fm_key, fm_val in pp.items(): for to_key, to_val in f(fm_key, fm_val, x): dp[to_key] = op(dp.get(to_key, e), to_val) return dp def f(k, v, x): global ans m, lt = k # (使った文字種, 未満か) p = x if lt: # 使った文字を末尾に置く yield (m, True), v * m if m < 26: # 未使用の文字を末尾に置く yield (m+1, True), v * (26 - m) if m >= K: ans += v * m if m < 26 and m+1 >= K: ans += v * (26 - m) ans %= MOD elif p == 0: nm = 1 cnt = ds[p] # より小さい文字 if cnt > 0: yield (nm, True), cnt if K == 1: ans += cnt ans %= MOD yield (0, False), 1 # not lt を維持 if K == 1 and p+1 < N: # 先頭p文字が S に一致する部分列の分 ans += 1 ans %= MOD elif p < N: used = used_masks[p-1] # 使ったビット used_less = used & ((1 << max(0, ds[p]-1)) - 1) # 使ったビット(いま見ている文字より小さい) used_cnt = used.bit_count() used_less_cnt = used_less.bit_count() if used_less_cnt > 0: # 使ったビットから選ぶ(より小さい文字) yield (used_cnt, True), v * used_less_cnt if used_cnt >= K: ans += v * used_less_cnt ans %= MOD # 使っていないビットから選ぶ(より小さい文字) unused_less_cnt = ds[p] - used_less_cnt if unused_less_cnt > 0: yield (used_cnt+1, True), v * unused_less_cnt if used_cnt+1 >= K: ans += v * unused_less_cnt ans %= MOD # # 文字 x より小さい文字を置く # for i in range(26): # if i >= cs[p]: break # if p == 0: # nm = 0 # b = 0 # else: # nm, b = kinds[p-1] # if not (b & (1 << i)): # nm += 1 # yield (nm, True), v # # if nm >= K: # ans += v # ans %= MOD if p+1 < N and used_masks[p].bit_count() >= K: ans += 1 ans %= MOD # not lt を維持 yield (0, False), v def op(a, b): return (a + b) % MOD def digit_dp(): init = {(0, False): 1} accum_dp(range(M), f, op, 0, init) MOD = 998244353 N, M, K = map(int, input().split()) S = input() ds = [ord(c) - ord('a') for c in S] b = 0 used_masks = [] # i 番目までで使われている文字種(ビット) for d in ds: b |= (1 << d) used_masks.append(b) ans = 0 digit_dp() print(ans)