NOI Online 2022 入門組 字串 第三題題解
阿新 • • 發佈:2022-04-04
看著就很想用記憶化搜尋是吧
設 \(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; } }