NOI Online 2022 入门组 字符串 第三题题解
看着就很想用记忆化搜索是吧
设 \(dp_{i,j,k,l}\) 表示决策到 \(S\) 的第 \(i\) 位, \(R\) 中有 \(j\) 位无需删除,而且需要删除 \(R\) 的前 \(k\) 位和后 \(l\) 位。
那么我们分类讨论:
\(1. S_i = -\),那么 \(dp_{i,j,k,l}\) 可以转移到 \(dp_{i + 1,j,k,l - 1}\) 和 \(dp_{i + 1,j,k - 1,l}\),也就是可以删除首位或者末位。
\(2.S_i≠ -\) 那么 \(dp_{i,j,k,l}\) 可以转移到 \(dp_{i + 1,j,k,l + 1}\),也就是说以后会被当做删除末位操作。
\(3. S_i ≠-\) 且 \(j=0\) 且 \(l=0\),那么 \(dp_{i,j,k,l}\) 可以转移到 \(dp_{i + 1,j,k + 1,l}\),也就是以后会被当做删除首位来操作。(\(j=0\) 且 \(l=0\) 表示当前前面所有位置都被当做删除首位来处理)。
\(4. S_i ≠ -\) 且 \(S_i = T_i\) 且 \(l = 0\),那么 \(dp_{i,j,k,l}\) 可以转移到 \(dp_{i + 1,j + 1,k,l}\),也就是永远不删除该位。
但是这个四维显然 MLE 了(((
但是可以发现, \(j+k+l=i\) !
于是压缩掉一维,AC辣!!!
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 405;
int n, m;
string s, t;
ll dp[N][N][N];
ll slove (int i, int j, int k, int l) {
if (i > n) {
return j == m && !k && !l;
}
if (~dp[i][j][k]) {
return dp[i][j][k];
}
ll res = 0;
if (s[i - 1] == '-') {
if (k) {
res = (res + slove (i + 1, j, k - 1, l)) % mod;
}
if (l) {
res = (res + slove (i + 1, j, k, l - 1)) % mod;
}
}
else {
res = slove (i + 1, j, k, l + 1) % mod;
if (!j && !l) {
res = (res + slove (i + 1, j, k + 1, l)) % mod;
}
if (s[i - 1] == t[j] && !l) {
res = (res + slove (i + 1, j + 1, k, l)) % mod;
}
}
return dp[i][j][k] = (res % mod);
}
int main () {
int T;
cin >> T;
while (T --) {
cin >> n >> m >> s >> t;
memset (dp, -1, sizeof (dp));
cout << slove (1, 0, 0, 0) % mod << endl;
}
}