zoukankan      html  css  js  c++  java
  • 最长公共上升子序列的学习

    方法1:O($n^2m^2$)

    学过dp的都知道。

     

    方法2:O($nm imes min(n,m)$)

    我们重新定义dp[i][j]:表示a[1…i]和b[2…j]上的LICS, 并且在b中的结束位置为j(重点)。

    那么有:

    $egin{cases} &dp[i][j]=dp[i-1][j]  ,  a[i] eq b[j]\ &dp[i][j]=max(dp[i-1][k])+1(k<j,b[k]<b[j]) ,  a[i]=b[j] end{cases}$

    方法3:O($nm$)

    根据方法2改进。

    我们先来看一看方法2的代码:

    for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) {

      if(a[i]!=b[j]) dp[i][j]=dp[i-1][j];

      else {

      for(k=1;k<j;++k) if (dp[i][j]<dp[i-1][k] && b[k]<b[j])  dp[i][j] = dp[i-1][k];

      dp[i][j]+=1;

      }

    }

    这个代码肯定是在循环k的部分优化。准确来说就是把k的那一层循环给搞掉。

    具体怎么搞掉呢?

    我们知道,当$a[i]=b[j]$时,我们可以将$b[k]<b[j]$换成$b[k]<a[i]$。

    我们知道在最外层循环内部,$a[i]$是不变的。所以就可以。。。一边算dp[i][j],一边算$<a[i]$的$b[j]$所对应的最大的LICS(就是dp[i-1][j])。

    具体代码:

    for(int i=1;i<=n;++i) {
      maxlen=0;f=0;
      for(int j=1;j<=m;++j) {
        dp[i][j]=dp[i-1][j];
        from[i][j]= i>1&&ok(i-1,j)? (i-1)*10000+j : from[i-1][j];
        if(a[i]==b[j]) dp[i][j]=maxlen+1,from[i][j]=f;
        if(b[j]<a[i] && dp[i-1][j]>maxlen) {
        maxlen=dp[i-1][j];
        f= i>1&&ok(i-1,j)? (i-1)*10000+j : from[i-1][j];
        }
      }
    }

    弱者就是会被欺负呀
  • 相关阅读:
    理解SetCapture、ReleaseCapture、GetCapture(控制了消息发往哪个窗口,是理解消息的关键)
    Javascript 的addEventListener()及attachEvent()区别分析
    鼠标拖拽
    鼠标右键菜单
    keydown
    一串跟随鼠标的DIV
    event对象和事件冒泡
    发表说说
    文档流
    CSS3 @keyframes 规则
  • 原文地址:https://www.cnblogs.com/Serene-shixinyi/p/7638834.html
Copyright © 2011-2022 走看看