zoukankan      html  css  js  c++  java
  • 《训练指南》——7.25

    Uva10635:

      有两个长度为p+1,q+1的序列A、B,每个序列的各个元素互不相同,且都是1~n^2的整数。两个序列的第一个元素均为1.求出A和B的最长公共子序列长度。

      分析:乍一看是典型的LCS问题,但是我们一考察数据发现n = 250 * 250结合LCS问题O(pq)的时间复杂度,使得这个问题需要必要的优化技巧。

      我们从题目描述出发,这里有一个很关键的要素是,两个序列各个序列中的元素互不相同,因此每个数据和其位置坐标将形成一一对应的关系,那么我们用num1[i]记录A序列中整数i的下标, 同时在输入B序列时,我们用num2[i]表示下标为i的整数x在A序列中的下标ai。那么现在我们考察序列num2[],我们会得到如下两组序列:

      x0 x1 x2 x3 …xi...

      a0 a1 a2 a3 …ai...

      1    2   3   4 …  i...

      其含义为,在A、B中共有的元素xi在序列A中的下标是ai , 在序列B中的下标是i。做这样一个复杂的数组的意义到底是什么呢?我们会发现,基于LCS的定义,联系下标,我们能够发现,公共子序列C中的各个元素在序列A、B中的下标序列均为是严格的递增,那么回到这个问题来,元素在序列B中的下标是1,2,3,4…显然是严格递增的了,也就是说,所谓的LCS问题,由于这道问题的特殊限制(每个序列的各个元素互不相同),我们可以将LCS问题转化成num2[]数组的LIS问题,而处理LIS问题我们有O(nlogn)的算法,而制作num1、num2两个数组的时间复杂度几乎是忽略不计的(伴随输入过程进行构造)。

      简单的参考代码如下。

    #include<cstdio>
    
    #include<cstring>
    
    #include<algorithm>
    
    using namespace std;
    
    const int maxn = 250 * 250;
    
    int S[maxn] , g[maxn] , dp[maxn];
    
    int num[maxn];
    
    const int INF = 1000000000;
    
     
    
    int main()
    
    {
    
         int t;
         int tt = 1;
         scanf("%d",&t);
    
         while(t--)
    
         {
    
            int n , p , q , x;
    
             scanf("%d%d%d",&n,&p,&q);
    
              for(int i = 1;i <= p + 1;i++)
    
              {
    
                    scanf("%d",&x);
    
                    num[x] = i;
    
              }
    
              int index = 0;
    
              for(int i = 1;i <= q + 1;i++)
    
              {
    
                   scanf("%d",&x);
    
                   if(num[x])  S[index++] = num[x];
    
              }
    
     
    
              for(int i = 0;i < index;i++)
    
                     g[i] = INF;
    
              int Max = 0;
    
              for(int i = 0;i < index;i++)
    
              {
    
                    int k = lower_bound(g + 1 , g + index + 1 , S[i]) - g;
    
                    dp[i] = k;
    
                    g[i] = S[i];
    
                    Max = max(Max , dp[i]);
    
              }
    
     
    
              printf("Case %d: %d
    ",tt,Max);
    
              tt++;
    
         }
    
    }
  • 相关阅读:
    PHP rsort() 函数
    PHP shuffle() 函数
    PHP sizeof() 函数
    PHP sort() 函数
    导入Orabbix_export_full.xml模板报错:主机群组 "Templates" 已存在.
    要让CLR挂掉的话……
    要让CLR挂掉的话……
    Windows 10 快捷键汇总表格
    Windows 10 快捷键汇总表格
    VisualStudio 合并代码文件
  • 原文地址:https://www.cnblogs.com/rhythmic/p/5702862.html
Copyright © 2011-2022 走看看