Description
给出两个由小于等于 \(k\) 的正整数构成的数列 \(A\) 与 \(B\) ,长度为 \(n\) 与 \(m\) 。
现在需要一个由小于等于 \(k\) 的正整数构成的数列 \(C\) ,使得 \(C\) 既不是 \(A\) 的子序列,也不是 \(B\)
的子序列。
请求出 \(C\) 的最小长度。
\(n,m,k\le 4000\)
Solution
\(dp[i][j]\) 表示 \(A\) 扫到 \(i\) , \(B\) 扫到 \(j\) , \(C\) 的最小长度。
预处理一下下一个与当前位置值相同的位置就好了。
#include<bits/stdc++.h>
using namespace std;
template <class T> inline void read(T &x) {
x = 0; static char ch = getchar(); for (; ch < '0' || ch > '9'; ch = getchar());
for (; ch >= '0' && ch <= '9'; ch = getchar()) (x *= 10) += ch - '0';
}
#define N 4010
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define drp(i, a, b) for (int i = a; i >= b; i--)
int n, m, K, a[N], b[N], dp[N][N], f1[N][N], f2[N][N], ans;
inline void upd(int& x, int y) { if (!x || x > y) x = y; }
int main() {
read(n), read(m), read(K);
rep(i, 1, n) read(a[i]);
rep(i, 1, m) read(b[i]);
drp(i, n, 1) {
rep(j, 1, K) f1[i][j] = f1[i + 1][j];
f1[i][a[i]] = i;
}
drp(i, m, 1) {
rep(j, 1, K) f2[i][j] = f2[i + 1][j];
f2[i][b[i]] = i;
}
dp[0][0] = 1, ans = min(n, m) + 1;
rep(i, 0, n) rep(j, 0, m) if (a[i] == b[j] && dp[i][j]) rep(k, 1, K)
if (!f1[i + 1][k] && !f2[j + 1][k]) ans = min(ans, dp[i][j]);
else upd(dp[f1[i + 1][k]][f2[j + 1][k]], dp[i][j] + 1);
printf("%d", ans);
return 0;
}