题目链接:传送门
思路:由题意知道,首先输入的颜色序列中,颜色是不重复的,于是可以记录每个颜色的出现位置f[a[i]]。然后遍历待去重的串,对每个字符,根据刚才记录的位置,可以判断这个字符只能出现在j <= f[a[i]]的位置,然后进行dp ,状态转移方程为:
dp[t] = max(dp[j] + 1) (j>= 0 && j <= f[a[i]] , t = f[a[i]]) 表示 以b[t]字符结尾的合法串的最大长度 , b是要求达成的颜色序列。
还可以直接套最长非递减子序列的模板,慢一点。
代码:
随缘dp: 6ms
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e4 + 5 , N = 205;
int a[maxn];
int f[N] , dp[N] , b[N];
int main() {
int n , m , l;
ios::sync_with_stdio(0);
cin >> n;
cin >> m;
memset(f , -1 , sizeof(f));
for(int i = 0 ; i < m ; i++) {
cin >> b[i];
f[b[i]] = i + 1;
}
cin >> l;
for(int i = 0 ; i < l ; i++) {
cin >> a[i];
}
int ans = 0;
for(int i = 0 ; i < l ; i++) {
int t = f[a[i]] - 1 , tmp = 0;
for(int j = 0 ; j < f[a[i]]; j++) {
tmp = max(tmp , dp[j] + 1);
}
if(t >= 0) {
dp[t] = tmp;
ans = max(dp[t] , ans);
}
}
cout << ans << "\n";
return 0;
}
1e8的暴力,直接非递减子序列,跑了87ms,。。数据怕是有点水。。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e4 + 5 , N = 205;
int a[maxn];
int f[N] , dp[maxn] , b[N];
int main() {
int n , m , l;
ios::sync_with_stdio(0);
cin >> n;
cin >> m;
memset(f , -1 , sizeof(f));
//memset(dp , -1 , sizeof(dp));
for(int i = 0 ; i < m ; i++) {
cin >> b[i];
f[b[i]] = i + 1;
}
cin >> l;
for(int i = 0 ; i < l ; i++) {
cin >> a[i];
}
int ans = 0;
for(int i = 0 ; i < l ; i++) {
if(f[a[i]] == -1)continue;
dp[i] = 1;
for(int j = 0 ; j < i ; j++) {
if(f[a[j]] <= f[a[i]] && f[a[j]] > -1) {
dp[i] = max(dp[i] , dp[j] + 1);
}
}
ans = max(ans , dp[i]);
}
cout << ans << "\n";
return 0;
}