1. 程式人生 > 其它 >NOI Online 2022 入門組 字串 第三題題解

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;
	}
}