相对于一般的LCS来说,这个问题可以直接得到某个字符在字符串内的位置。
先把第一个串读入,处理出每个字符出现的位置。
然后枚举第二个串,对于当前的字符,直接枚举这个字符在第一个串里出现的位置,然后转移。
转移需要用到前缀最大值,用树状数组来维护。
orz神题。
/* Pigonometry */
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn = 20005, maxm = (maxn << 2) + maxn;
int n, m, cnt[maxn][7], dp[maxm], tr[maxm];
inline int iread() {
int f = 1; int x = 0; char ch = getchar();
for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1;
for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
return f * x;
}
inline void change(int x, int c) {
for(; x <= m; x += x & -x) tr[x] = max(tr[x], c);
}
inline int query(int x) {
int res = 0;
for(; x; x -= x & -x) res = max(res, tr[x]);
return res;
}
int main() {
n = iread(); m = (n << 2) + n;
for(int i = 1; i <= m; i++) {
int x = iread();
cnt[x][++cnt[x][0]] = i;
}
int ans = 0;
for(int i = 1; i <= m; i++) {
int x = iread();
for(int j = 5; j >= 1; j--) {
int pos = cnt[x][j], tmp = query(pos - 1) + 1;
if(dp[pos] < tmp) dp[pos] = tmp, change(pos, tmp);
}
}
for(int i = 1; i <= m; i++) ans = max(ans, dp[i]);
printf("%d\n", ans);
return 0;
}