Solution
注意到 由左右两个相同的 夹着一个新字符 拼接而来。所以可以尝试从 的答案转移得到 的答案。
设 表示 的 以子序列形式在 中出现的次数,并初始化为 。首先考虑到 中含有两个 ,因此枚举所有区间把 加到 中。接下来继续枚举所有区间,转移过程分类讨论:
-
的 中不含 。此时枚举区间断点 ,有
-
的 中不含 。此时枚举区间断点 ,表示 。有
或 的情况需要特判讨论。
答案即为 。时间复杂度 。
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 105, mod = 998244353;
ll f[N][N][N], n, m, maxl;
char s[N], t[N];
int main()
{
scanf("%s%s", s + 1, t + 1);
n = strlen(s + 1); m = strlen(t + 1);
maxl = 1;
for (int i = 1; i <= n; i++) {
ll len = min(m, maxl);
if (maxl <= m)
maxl = maxl * 2 + 1;
for (int l = 1; l <= m; l++) {
for (int r = l; r <= min(l + len - 1, m); r++) {
f[i][l][r] = (f[i - 1][l][r] << 1) % mod;
for (int k = l; k <= r; k++) {
if (k < r)
f[i][l][r] = (f[i][l][r] + f[i - 1][l][k] * f[i - 1][k + 1][r] % mod) % mod;
if (t[k] != s[i]) continue;
ll mul = 1;
if (k > l)
mul = (mul * f[i - 1][l][k - 1]) % mod;
if (k < r)
mul = (mul * f[i - 1][k + 1][r]) % mod;
f[i][l][r] = (f[i][l][r] + mul) % mod;
}
}
}
}
printf("%lld", f[n][1][m]);
return 0;
}