最长公共子序列

来源:互联网 发布:安卓软件编程入门 编辑:程序博客网 时间:2024/05/01 02:55

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

33 2 1 2 1 34 2 1 3 43 2 4 10
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);      }  }




0 0