题意:给出两个串,输出最长公共子序列。
题解:直接用n^2的方法会超时,需要将问题转化成计算最长上升子序列,然后可以用二分来减小时间复杂度。
方法是用一个数组将第一个串内元素在第二个串内的位置保存下来,然后将这个数组的最长上升子序列长度求出就是解。
#include <stdio.h>
#include <string.h>
#include <map>
#include <algorithm>
using namespace std;
const int N = 62500;
int n, p, q;
int s1[N], s2[N];
map<int, int> pos;
int LIS(int len) {
int k = 1;
s2[1] = s1[1];
for (int i = 2; i <= len; i++) {
if (s1[i] > s2[k])
s2[++k] = s1[i];
else {
int l = 1, r = k, mid;
while (l < r) {
mid = (l + r) / 2;
if (s2[mid] < s1[i])
l = mid + 1;
else
r = mid;
}
s2[l] = s1[i];
}
}
return k;
}
int main() {
int t, cas = 1;
scanf("%d", &t);
while (t--) {
pos.clear();
scanf("%d%d%d", &n, &p, &q);
int temp;
for (int i = 1; i <= p + 1; i++) {
scanf("%d", &temp);
pos[temp] = i;
}
int k = 1;
for (int i = 1; i <= q + 1; i++) {
scanf("%d", &temp);
if (pos[temp])
s1[k++] = pos[temp];
}
printf("Case %d: %d\n", cas++, LIS(k - 1));
}
return 0;
}