LICS O(n*m)+前驱路径

LICS:最长公共上升子序列;

一般令f[i][j]表示a串前i位,b串以j结尾的LICS长度。于是,答案为:max(1~m)(f[n][i]);

朴素做法:O(n^3) 相等时,从1~j-1枚举最大值。

for(int i=1;i<=n;i++)
  for(int j=1;j<=m;j++)
  {if(a[i]!=b[j]) f[i][j]=f[i-1][j];
   else if(a[i]==b[j])
    for(int k=1;k<j;k++)
        if(b[k]<b[j]) f[i][j]=f[i-1][k];
       }

算法时间复杂度改进思路主要从优化第三层(k)复杂度入手。

升级做法: O(n^2logn) 利用树状数组记录f[i-1][1~j-1]最大值; 数组下表记录的是b串数值。 (第一个j循环预处理,并且更新上一次的成果)需要:树状数组和离散化。

int mx[]
for(int i=1;i<=n;i++)
{
 for(int j=1;j<=m;j++)
 {mx[j]=query(b[j]-1)//0~b[j]-1 这些数中的f最大值
 modify(b[j],f[i-1][j])//将上一轮求出的f尝试更新
 }
 for(int j=1;j<=m;j++)
  if(a[i]==b[j]) f[i][j]=mx[j]+1;
  else f[i][j]=f[i-1][j];
}

其实这样很麻烦。 复杂度中等,还需要离散化,求具体子序列还要还原。

终极做法:O(n^2) 考虑到,每次进行j循环时,i不动,a[i]的值暂时不变。所以只需边求边记录最大值即可。 直接省掉k层循环。

for(int i=1;i<=n;i++)
 {
  int mx=f[i-1][0];
  for(int j=1;j<=m;j++)
   if(a[i]!=a[j])
    f[i][j]=f[i-1][j]
   else
    f[i][j]=mx+1;
   if(b[j]<a[i])//j即将变成j+1,尝试更新mx(只有b[j]<a[i]才可以保证上升)
    mx=max(mx,f[i][j])
 }

poj 2127 至于要求具体子序列时,需要记录使之更新的前驱,即path[i][j]=某个位置bj; 因为是“以j结尾”,所以记录bj。输出时输出b[bj];

详见代码: ai,aj记录使答案成为ans的第一个位置。 故可以直接输出b[aj];

#include<cstdio>
#include<cstdlib>
#include<iostream>
using namespace std;
const int N=505;
int f[N][N],path[N][N];
int mj,mx,sum,ai,aj;
int ans[N];
int n,m;
int a[N],b[N];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
     scanf("%d",&a[i]);
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
     scanf("%d",&b[i]);
    for(int i=1;i<=n;i++)
    {
     mx=0;
     for(int j=1;j<=m;j++)
     {
        f[i][j]=f[i-1][j];
        path[i][j]=-1;
        if(b[j]<a[i]&&f[i-1][j]>mx)
        {
            mx=f[i-1][j];
            mj=j;
        }
        else if(a[i]==b[j])
        {
            f[i][j]=mx+1;
            path[i][j]=mj;
        }
        if(sum<f[i][j])
        {
            sum=f[i][j];
            ai=i;
            aj=j;
        }
     }
    }
    printf("%d\n",sum);
    int tmp=sum;
    while(tmp)
    {
        if(path[ai][aj]>-1)
        {
            ans[tmp--]=b[aj];
            aj=path[ai][aj];
        }
        ai--;
    }
    for(int i=1;i<=sum;i++)
     printf("%d ",ans[i]);
    return 0;
}

纯手打。 参考:https://www.cnblogs.com/dream-wind/archive/2012/08/25/2655641.html

原文地址:https://www.cnblogs.com/Miracevin/p/9031701.html

时间: 2024-10-14 23:55:07

LICS O(n*m)+前驱路径的相关文章

最大前驱路径

最大前驱路径是什么呢? 比如, 用户在页面中的访问路径是 1,2,3,4 但是,用户不会按照正常设定好的路径进行访问, 用户的访问路径可能是 1,2,5,2 这时候,我们就要从访问路径中提取出 1,2,5 起始仔细观察发现也很简单, 思路如下: 输入 1,2,5 当再次输入 2 时,我们发现这是一个回退事件, 进行回退, 并处理本条路径 1,2,5, 完美 是不是很简单, 但是,路径肯定是不止一条的, 可能用户的访问路径是这样的, {1,2,3,5,3,4,3,2,1,6}, 那么对应的访问路径

关于自动寻径和图、邻接表的学习和启发

以后的游戏中可能会用到人物的自动寻径,在网上看到一个非常不错的博文,特学习了一下,并转了过来为以后留着... 再次感谢 Siliphen的分享,本文转载自 http://blog.csdn.net/stevenkylelee/article/details/38408253 本文乃Siliphen原创,转载请注明出处:http://blog.csdn.net/stevenkylelee 本文的实现使用的环境是:Cocos2d-x 3.2,VS2013 本文,我们最终实现的地图行走效果如下2图:

Cocos2d-x 地图行走的实现:图论与Dijkstra

本文乃Siliphen原创,转载请注明出处:http://blog.csdn.net/stevenkylelee 本文的实现基于Cocos2d-x 3.2. 本文,我们最终实现的地图行走效果如下2图: 下面是2张屏幕录制的gif动画图,有点大,看不到的话,耐心等待一下,或者刷新页面试试. 地图行走用于现实的地图上. 1.什么是地图行走 很多游戏会有一个"世界"的概念.玩家在这个世界中行走,到达不同的地方去执行的任务,打怪或者是触发剧情等.下图是<锁链战记>的世界地图的截图.

A&#215;算法:

  In games we often want to find paths from one location to another. We’re not just trying to find the shortest distance; we also want to take into account travel time. In this map, walking through water is significantly slower, so we want to find a

最短路(最短路之积)

首先考虑暴力维护,显然极端数据就会炸裂,那么用什么来维护呢? 考虑一个很 NB 的公式log(n*m)=log(n)+log(m) OK ,这道题到此结束 我们只要把乘积转化为对数,最后再还原就可以了,也不用考虑精度问题,本蒟蒻试着用pow,然后它死了. 代码 #include<bits/stdc++.h> using namespace std; const int mod=9987; const int N=1e3+5; const int M=1e6+5; int head[N],tot

hiho 第118周 网络流四&#183;最小路径覆盖

描述 国庆期间正是旅游和游玩的高峰期. 小Hi和小Ho的学习小组为了研究课题,决定趁此机会派出若干个调查团去沿途查看一下H市内各个景点的游客情况. H市一共有N个旅游景点(编号1..N),由M条单向游览路线连接.在一个景点游览完后,可以顺着游览线路前往下一个景点. 为了避免游客重复游览同一个景点,游览线路保证是没有环路的. 每一个调查团可以从任意一个景点出发,沿着计划好的游览线路依次调查,到达终点后再返回.每个景点只会有一个调查团经过,不会重复调查. 举个例子: 上图中一共派出了3个调查团: 1

学霸的迷宫(BFS+记录路径)

1 //求从(sx.sy)到(gx.gy)的最短距离; 2 3 #include<iostream> 4 #include<cstdio> 5 #include<cstdio> 6 #include<queue> 7 #include<cstring> 8 #define INF 99999999 9 10 using namespace std; 11 12 typedef pair<int, int > P; //数对,记录位置

HDU 1026 Ignatius and the Princess I(BFS+路径输出)

Ignatius and the Princess I Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 19800    Accepted Submission(s): 6452Special Judge Problem Description The Princess has been abducted by the BEelzebub

HDU1026--Ignatius and the Princess I(BFS记录路径)

Problem Description The Princess has been abducted by the BEelzebub feng5166, our hero Ignatius has to rescue our pretty Princess. Now he gets into feng5166's castle. The castle is a large labyrinth. To make the problem simply, we assume the labyrint