题解:AT_abc391_g [ABC391G] Many LCS
dayz_break404 · · 题解
dp 套 dp 板子题。
考虑固定构成的字符串为
考虑将其作为外层 dp 数组的一层状态,那么转移就相当于就是枚举当前加入哪一个字符,根据当前的字符来更新内层 dp 数组的状态。
将数组作为状态的一维显然不现实,将内层 dp 看作一个二维表格,每次在
内层就是一个 DFA 转移的过程,预处理转移函数
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x*f;
}
#define ll long long
const int mod=998244353;
const int maxn=1030;
ll t,n,m,nxt[maxn][27],dp[101][maxn],a[maxn],g[maxn],h[maxn],ans[maxn];
char s[20];
int main(){
n=read(),m=read();
cin>>(s+1);
for(int i=1;i<=n;i++) a[i]=s[i]-'a';
for(int s=0;s<(1<<n);s++){
for(int i=1;i<=n;i++) g[i]=g[i-1]+((s>>(i-1))&1);
for(int i=0;i<=25;i++){
for(int j=1;j<=n;j++){
if(i==a[j]) h[j]=g[j-1]+1;
else h[j]=max(g[j],h[j-1]);
}
int now=0;
for(int j=1;j<=n;j++) now+=((h[j]-h[j-1])<<(j-1));
nxt[s][i]=now;
}
}
dp[0][0]=1;
for(int i=0;i<m;i++){
for(int s=0;s<(1<<n);s++){
for(int j=0;j<=25;j++) dp[i+1][nxt[s][j]]=(dp[i+1][nxt[s][j]]+dp[i][s])%mod;
}
}
for(int i=0;i<(1<<n);i++) (ans[__builtin_popcount(i)]+=dp[m][i])%mod;
for(int i=0;i<=n;i++) printf("%lld ",ans[i]%mod);
return 0;
}