您的位置:首页 > 其它

UVA-10635 LCS转化为LIS

2017-11-09 22:33 423 查看
题意:给定两个序列一个长度为p+1,一个为q+1,求两序列的LCS,序列中每个数字不重复,最大值为n*n,n不大于250。

思路:每个数都不重复,所以可以将源数据和下标置换,对数列做一个哈希变换,另一个数列也做相同的变换就可以的到一个新的数列。可以转换为求新序列的LIS。时间复杂度就会降到O(nlogn)。原因可以这样思考,由于b中的数字是通过a的变换得到的,所以b的所有子集都是a的一个子集,但是顺序不确定。考虑b的LIS,它一定是a的一个子集,这个子集是a中从左到右的(b中的递增序列),所以一定是b和a的公共序列,由于LIS最长,所以是LCS。

#include <stdio.h>
#include <algorithm>
#include <math.h>
#include <string>
#include <cstring>
#include <map>
#include <vector>
#include <iostream>
#include <string.h>
using namespace std;

typedef long long ll;
const int maxn = 300*300;

int dp[maxn];
int a[maxn],b[maxn];
int n,p,q;

int lis()
{
memset(dp,0,sizeof(dp));
int len=1;
dp[0]=b[0];
for(int i=1;i<q+1;i++){
int pos=lower_bound(dp,dp+len,b[i])-dp;
dp[pos]=b[i];
len=max(len,pos+1);
}
return len;
}

int main()
{
int t,kase=1;
scanf("%d",&t);
while(t--){
scanf("%d%d%d",&n,&p,&q);
for(int i=0;i<p+1;i++){
int tmp;
scanf("%d",&tmp);
a[tmp]=i+1;
}

for(int i=0;i<q+1;i++){
int tmp;
scanf("%d",&tmp);
b[i]=a[tmp];
}
int ans=lis();
printf("Case %d: %d\n",kase++,ans);
/*for(int i=0;i<q+1;i++)
printf("%d ",b[i]);
printf("\n");*/
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  UVA