最长公共子序列

介绍了一个最长公共子序列问题的特殊场景,即两序列由1到N的不同整数组成时的高效求解方法。利用动态规划原理,在这种情况下,算法的时间复杂度降低,并通过实例演示了如何寻找两个序列的最长公共子序列。

最长公共子序列
Time Limit: 4000ms, Special Time Limit:10000ms, Memory Limit:65536KB
Total submit users: 50, Accepted users: 36
Problem 11313 : No special judgement
Problem description
  一个数列S,如果分别是两个已知数列的子序列,且是所有符合此条件序列中最长的,则 S 称为这二个序列的最长公共子序列。 
Seat26最近很无聊,就去研究最长公共子序列,不过他发现这个问题已经被许多人解决了,没有什么好研究的,他想,要是给定的二个序列没有重复的元素会不会有更好的解法呢?
Input
  输入有多组数据,每组数据包括三行,第一行有个正整数N,(1<=N<=100000,)
第二,三行有N个数,分别表示第一个数列和第二个数列,每个数列均是1到N的一个排列,最后一行是0,表示输入结束且不需要处理。
最后一行是0,表示输入结束且不需要处理。
Output
  对于每一组数据,输出S的长度.
Sample Input
3
3 2 1 
2 1 3
4 
2 1 3 4
3 2 4 1
0
Sample Output
2 
2
Problem Source
  湖南师范大学第四届大学生计算机程序设计竞赛

一般的最长公共子序列都通过动态规划解决的。时间是O(n*n),空间可以优化到O(n)。这题特殊在是1到n的一个组合,就是元素不会出现重复。记录串1在串2中的位置数组a[],a中的最长上升子序列就是答案。

#include<iostream>  
#include<algorithm>  
#include<string.h>  
using namespace std;  
const int N=100005;  
  
int loc[N],a[N];  
int stack[N];  
#define inf 0x3f3f3f3f  
int LIS(int n){  
    memset(stack,inf,sizeof stack);  
    for(int i=0;i<n;i++){  
        int loc=lower_bound(stack,stack+n,a[i])-stack;  
        stack[loc]=a[i];  
    }  
    return lower_bound(stack,stack+n,inf)-stack;  
}  
int main(){  
    int n,t;  
    while(cin>>n&&n){  
        for(int i=0;i<n;i++){  
            scanf("%d",&t);  
            loc[t]=i;//记录值为t的位置  
        }    
        for(int i=0;i<n;i++){  
            scanf("%d",&t);  
            a[i]=loc[t];//找到值为t的位置放在a中 
        }  
        int ans=LIS(n);  
        printf("%d\n",ans);  
    }  
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值