zoukankan      html  css  js  c++  java
  • uva10635 LCS映射转LIS

    题目给定

    2个序列,要我们求LCS,但是序列的长度最长是250*250, LCS的时间复杂度是O(N*N),所以无法解决
    我们可以第一个序列的数字,按位置,映射为1、2、3、4、5、6、7、8、9
    那么就会得到一个映射函数,将第二个序列,映射为一个新的序列
    那么就相当于用一个映射函数将两个字符串映射为两个新的字符串
    我们会发现,LCS的长度是不会改变的
    因为两个序列中相同的字符映射之后仍然相同
    所以只要求两个序列的LCS即可
    然后我们发现,第一个序列是递增的,那么求出来的LCS肯定也是递增的
    那么我们是不是只要求第二个序列的最长递增子序列就可以了呢
    答案是:yes
    而LIS有 O(nlogn)的算法
    所以复杂度降低了,从而可以求解题目
     
     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <stdlib.h>
     4 #include <algorithm>
     5 #include <iostream>
     6 #include <queue>
     7 #include <stack>
     8 #include <vector>
     9 #include <map>
    10 #include <set>
    11 #include <string>
    12 using namespace std;
    13 typedef long long LL;
    14 const int INF = 1<<30;
    15 const int N = 90000;
    16 int a[N],b[N];
    17 int reflect[N];
    18 int st[N],top;
    19 int main()
    20 {
    21     int t,n,p,q,i,j,tCase;
    22     scanf("%d",&tCase);
    23     for(t=1; t<=tCase; ++t)
    24     {
    25         top = 0;
    26         scanf("%d%d%d",&n,&p,&q);
    27         p++;
    28         q++;
    29         for(i=1; i<=p; ++i)
    30         {
    31             scanf("%d",&a[i]);
    32             reflect[a[i]] = i;
    33         }    
    34         for(i=1; i<=q; ++i)
    35         {
    36             scanf("%d",&b[i]);
    37             b[i] = reflect[b[i]];
    38         }    
    39         st[top] = b[1];
    40         for(i=2; i<=q; ++i)
    41         {
    42             if(b[i] > st[top])
    43             {
    44                 st[++top] = b[i];
    45             }
    46             else
    47             {
    48                 int low = 0, high = top;
    49                 while(low <= high)
    50                 {
    51                     int mid = (low + high) >> 1;
    52                     if(b[i] > st[mid])
    53                         low = mid + 1;
    54                     else
    55                         high = mid - 1;
    56                 }
    57                 st[low] = b[i];
    58             }    
    59         }
    60         printf("Case %d: %d
    ",t,top+1);
    61     }
    62     
    63     return 0;
    64 }
    View Code

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

    hdu的魔板也是用了映射,从而变成预处理,然后读入数据,能马上输出答案。

  • 相关阅读:
    Calendar来进行一个时间段内每天的判断
    关于PreparedStatement的setDate的了解
    git学习--创建标签
    git学习--bug分支
    hibernate(1)
    JavaScript(三)---- 控制流程语句
    JavaScript(二)---- 变量、数据类型和运算符
    JavaScript(一)---- 概述
    css(四)-- 盒子模型和定位
    css(三)-- 常用属性
  • 原文地址:https://www.cnblogs.com/justPassBy/p/4395627.html
Copyright © 2011-2022 走看看