您的位置:首页 > 其它

uva10635 LCS映射转LIS

2015-04-06 11:14 176 查看
题目给定

2个序列,要我们求LCS,但是序列的长度最长是250*250, LCS的时间复杂度是O(N*N),所以无法解决
我们可以第一个序列的数字,按位置,映射为1、2、3、4、5、6、7、8、9
那么就会得到一个映射函数,将第二个序列,映射为一个新的序列
那么就相当于用一个映射函数将两个字符串映射为两个新的字符串
我们会发现,LCS的长度是不会改变的
因为两个序列中相同的字符映射之后仍然相同
所以只要求两个序列的LCS即可
然后我们发现,第一个序列是递增的,那么求出来的LCS肯定也是递增的
那么我们是不是只要求第二个序列的最长递增子序列就可以了呢
答案是:yes
而LIS有 O(nlogn)的算法
所以复杂度降低了,从而可以求解题目

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <string>
using namespace std;
typedef long long LL;
const int INF = 1<<30;
const int N = 90000;
int a
,b
;
int reflect
;
int st
,top;
int main()
{
int t,n,p,q,i,j,tCase;
scanf("%d",&tCase);
for(t=1; t<=tCase; ++t)
{
top = 0;
scanf("%d%d%d",&n,&p,&q);
p++;
q++;
for(i=1; i<=p; ++i)
{
scanf("%d",&a[i]);
reflect[a[i]] = i;
}
for(i=1; i<=q; ++i)
{
scanf("%d",&b[i]);
b[i] = reflect[b[i]];
}
st[top] = b[1];
for(i=2; i<=q; ++i)
{
if(b[i] > st[top])
{
st[++top] = b[i];
}
else
{
int low = 0, high = top;
while(low <= high)
{
int mid = (low + high) >> 1;
if(b[i] > st[mid])
low = mid + 1;
else
high = mid - 1;
}
st[low] = b[i];
}
}
printf("Case %d: %d\n",t,top+1);
}

return 0;
}


View Code
这道题目能够这样子转化是因为串中的数字是各不相同的,所以每个数字的映射是唯一的, 所以才能导致第一个串映射过后是递增的。

hdu的魔板也是用了映射,从而变成预处理,然后读入数据,能马上输出答案。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: