[LCS][LIS]Uva10635]

3 篇文章 0 订阅
3 篇文章 0 订阅

题目大意:求两个序列的LCS

一般来说,LCS复杂度O(n*n)

f[i][j]表示A串前i个,B串前j个的LCS
f[i][j]=f[i-1][j-1] (s1[i]==s2[j])
f[i][j]=max(f[i-1] [j],f[i][j-1])

但是

Input
The rst line of the input contains a single integer t (1 t 10), the number of test cases followed.
For each case, the rst line contains three integers n, p, q (2 n 250, 1 p; q < n n). The second
line contains p + 1 different integers in the range [1 : : : n n], the sequence of the Prince. The third line
contains q + 1 different integers in the range [1 : : : n n], the sequence of the Princess.
Output
For each test case, print the case number and the length of longest route. Look at the output for sample
input for details.
Sample Input
1
3 6 7
1 7 5 4 8 3 9
1 4 3 5 6 2 8 9
Sample Output
Case 1: 4

N是250*250,,所以n*n会爆掉,而且序列又不相同
所以可以把LCS转成LIS,,,

LCS->LIS原则:序列中字母或者数字各不相等。
做法:第一个序列映射,,转换第二个序列
1 5 3 7 2=1 2 3 4 5
5 9 3 7 2 1=2 0 3 4 5 1
注意,只有当找得到的映射才能计算,判断

复杂度:n*logn

#include<iostream>
#include<cstdio>
#include<ctime>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<algorithm>
#ifdef WIN32
#define AUTO "%I64d"
#else
#define AUTO "%lld"
#endif
#define INF 0x3f3f3f3f
#define clock CLOCKS_PER_SEC
#define cle(x) memset(x,0,sizeof(x))
#define maxcle(x) memset(x,127,sizeof(x))
#define mincle(x) memset(x,-1,sizeof(x))
#define cop(a,x) memcpy(x,a,sizeof(a))
#define FROP "Uva"
#define C(a,b) next_permutation(a,b)
#define LL long long
#define smin(x,tmp) x=min(x,tmp)
using namespace std;
const int N=655;
int mp[N*N],last[N*N],kase;
int a[N*N],b[N*N],ans;
int find(int x)
{
    int l=1,r=ans,tmp=0;
    while(l<=r)
    {
        int mid=(l+r)>>1;
        if(last[mid]<=x)tmp=mid,l=mid+1;
        else r=mid-1;
    }
    return tmp;
}
int main()
{
    freopen(FROP".in","r",stdin);
    freopen(FROP".out","w",stdout);
    int t;
    scanf("%d",&t);
    while(t--)
    {
        cle(a),cle(b),cle(mp),maxcle(last);
        int n,q,p;
        scanf("%d%d%d",&n,&q,&p);
        p++,q++;
        for(int i = 1; i<= q; i++)
            scanf("%d",&a[i]),mp[a[i]]=i;
        int pos=0;
        for(int i = 1; i<= p; i++)
        {
            int x;
            scanf("%d",&x);
            if(mp[x])b[++pos]=mp[x];
        }
        ans=0;
        for(int i = 1 ; i <= pos; i++)
        {
            int tmp=find(b[i]);
            if(last[tmp+1]>b[i])last[tmp+1]=b[i];
            ans=max(tmp+1,ans);
        }
        kase++;
        printf("Case %d: %d\n",kase,ans);
    }
    return 0;
}

调了很久,,发现数组开小了。。。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值