P1439 【模板】最长公共子序列(洛谷)
这道题LCS。
O(n^2)暴力不仅会tle还会RE。
暴力的话就是dp的那个式子。
这里给出对数时间处理的:
我们记录数组a[]的每个元素所在的下标,即把下标和对应的元素内容进行调换,得到pos[]。
然后我们把pos[]数组和b[]数组进行操作,查找b[i]在pos[]中对应的位置(即在a[]中对应的位置)。
求出pos[]数组的LIS(最长上升子序列)。长度就是最长公共子序列的长度。
因为我们的b[]数组是按顺序操作的,目的是想在b[]中找到最长的公共子序列,那么对应到a[]中的位置应该是递增的,所以这里就产生了pos[]数组。用LIS方法求得即可。
代码部分:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int a[N];
int b[N];
int pos[N];
int d[N];
int n;
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
{
scanf ("%d", &a[i]);
pos[a[i]] = i;
}
for (int i = 1; i <= n; i++)
{
scanf ("%d", &b[i]);
}
int len = 0;
for (int i = 1; i <= n; i++)
{
int now = pos[b[i]];
if (now > d[len])
{
d[++len] = now;
}
else
{
int t = lower_bound(d + 1, d + len + 1, now) - d;
d[t] = now;
}
}
cout << len << endl;
return 0;
}