这个与一般求LCS 不太相同,因为N太大, 先前学的是O(n*n),rep(i, n) rep(j, n):
现在N会到1e5,肯定会爆,那可以怎么优化呢?
1.把a数组每个数出现的顺序当做新编号放在num[]数组里,那么b数组就可以随之改变。即a数组变成1 2 3 4 5, 那么b可以相应变成3 2 1 4 5, 那么最长公共子序列显然就变成了求b数组的最长上升子序列。而最长上升子序列又可以用单调队列和二分优化;
2.单调队列:每次找到第一个大于等于b[i]的值的位置与b[i]替换,最终队列的长度就是最大公共子序列的长度;
2.这个方法只能适用于每个序列中没有重复元素的时候;
3.如果有的题b序列中有的数a中可能没有,那么把b序列变完之后记得要把0给去掉(a中没有这个数);
4.需要考虑3情况的,还有更多详细情况的可以看小蓝书P67。
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define ios ios::sync_with_stdio(false);cin.tie(0); cout.tie(0);
typedef pair<int, int> PII;
const double pi = acos(-1.0);
#define rep(i, n) for (int i = 1; i <= (n); ++i)
#define rrep(i, n) for (int i = n; i >= (1); --i)
typedef long long ll;
#define sqar(x) ((x)*(x))
inline int read() {
int s = 0, w = 1;
char ch = getchar();
while (ch < '0' || ch>'9') { if (ch == '-')w = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
return s * w;
}
const int N = 1e5 + 10;
int num[N], q[N];
int main(){
int n, temp;
n = read();
rep(i, n){
temp = read();
num[temp] = i;
}
int res = 1;
rep(i, n) q[i] = INF;
rep(i, n){
temp = read();
temp = num[temp];
int k = lower_bound(q + 1, q + 1 + n, temp) - q;
res = max(res, k);
q[k] = temp;
}
printf("%d", res);
return 0;
}