题解 P5404 【[CTS2019]重复】
EternalAlexander · · 题解
记
题意即求存在多少个
首先将限制转化为
设串
考虑枚举
同时,对于所有
我们考虑
那么我们知道,对应节点
考虑这个自动机的形式,对于任意节点,其不指向根的合法出边至多只有一条,否则对应字符较小的一条是不合法的。因此这个自动机的形式是,节点
同样枚举节点
#include <bits/stdc++.h>
#define ll long long
#define maxn 2005
const int mod = 998244353;
int n,m,max[maxn],nxt[maxn],ch[maxn][26],f[maxn][maxn],ans,sum=1;
char s[maxn];
int main(){
scanf("%d%s",&m,s+1);
n = std::strlen(s+1);
nxt[0] = -1; max[0] = 0;
for (int i = 1; i <= m; ++ i) sum = (ll) sum * 26 % mod;
for (int i = 1; i <= n; ++ i) {
int j = nxt[i-1];
while (j != -1 && s[j+1] != s[i]) j = nxt[j];
nxt[i] = j+1;
}
for (int i = 0; i <= n; ++ i)
for (int c = 0; c < 26; ++ c) {
if (s[i+1] - 'a' == c) ch[i][c] = i+1;
else ch[i][c] = (i!=0? ch[nxt[i]][c] : 0);
if (ch[i][c]) max[i] = c;
}
f[0][0] = 1;
for (int i = 0; i <= m; ++ i)
for (int j = 0; j <= n; ++j)
for (int c = max[j]; c < 26; ++ c)
f[i+1][ch[j][c]] = (f[i+1][ch[j][c]] + f[i][j]) % mod;
for (int i = 0; i <= n; ++ i) {
int u = i;
for (int j = 0; j < m; ++ j) {
ans = (ans + (ll) (26 - max[u] - 1) * f[m-j-1][i] % mod) % mod;
u = ch[u][max[u]];
if (!u) break;
}
ans = (ans + (u !=0 && u==i)) % mod;
} printf("%d",(sum - ans + mod) % mod);
return 0;
}