hdu 1423 最长公共递增子序列 LCIS
最长公共上升子序列(LCIS)的O(n^2)算法
预备知识:动态规划的基本思想,LCS,LIS。
问题:字符串a,字符串b,求a和b的LCIS(最长公共上升子序列)。
首先我们可以看到,这个问题具有相当多的重叠子问题。于是我们想到用DP搞。DP的首要任务是什么?定义状态。
1定义状态F[i][j]表示以a串的前i个字符b串的前j个字符且以b[j]为结尾构成的LCIS的长度。
为什么是这个而不是其他的状态定义?最重要的原因是我只会这个,还有一个原因是我知道这个定义能搞到平方的算法。而我这只会这个的原因是,这个状态定义实在是太好用了。这一点我后面再说。
我们来考察一下这个这个状态。思考这个状态能转移到哪些状态似乎有些棘手,如果把思路逆转一下,考察这个状态的最优值依赖于哪些状态,就容易许多了。这个状态依赖于哪些状态呢?
首先,在a[i]!=b[j]的时候有F[i][j]=F[i-1][j]。为什么呢?因为F[i][j]是以b[j]为结尾的LCIS,如果F[i][j]>0那么就说明a[1]..a[i]中必然有一个字符a[k]等于b[j](如果F[i][j]等于0呢?那赋值与否都没有什么影响了)。因为a[k]!=a[i],那么a[i]对F[i][j]没有贡献,于是我们不考虑它照样能得出F[i][j]的最优值。所以在a[i]!=b[j]的情况下必然有F[i][j]=F[i-1][j]。这一点参考LCS的处理方法。
那如果a[i]==b[j]呢?首先,这个等于起码保证了长度为1的LCIS。然后我们还需要去找一个最长的且能让b[j]接在其末尾的LCIS。之前最长的LCIS在哪呢?首先我们要去找的F数组的第一维必然是i-1。因为i已经拿去和b[j]配对去了,不能用了。并且也不能是i-2,因为i-1必然比i-2更优。第二维呢?那就需要枚举b[1]..b[j-1]了,因为你不知道这里面哪个最长且哪个小于b[j]。这里还有一个问题,可不可能不配对呢?也就是在a[i]==b[j]的情况下,需不需要考虑F[i][j]=F[i-1][j]的决策呢?答案是不需要。因为如果b[j]不和a[i]配对,那就是和之前的a[1]..a[j-1]配对(假设F[i-1][j]>0,等于0不考虑),这样必然没有和a[i]配对优越。(为什么必然呢?因为b[j]和a[i]配对之后的转移是max(F[i-1][k])+1,而和之前的i`配对则是max(F[i`-1][k])+1。显然有F[i][j]>F[i`][j],i`>i) 于是我们得出了状态转移方程:
a[i]!=b[j]: F[i][j]=F[i-1][j]
a[i]==b[j]: F[i][j]=max(F[i-1][k])+1 1<=k<=j-1&&b[j]>b[k]
不难看到,这是一个时间复杂度为O(n^3)的DP,离平方还有一段距离。
但是,这个算法最关键的是,如果按照一个合理的递推顺序,max(F[i-1][k])的值我们可以在之前访问F[i][k]的时候通过维护更新一个max变量得到。怎么得到呢?首先递推的顺序必须是状态的第一维在外层循环,第二维在内层循环。也就是算好了F[1][len(b)]再去算F[2][1]。 如果按照这个递推顺序我们可以在每次外层循环的开始加上令一个max变量为0,然后开始内层循环。当a[i]>b[j]的时候令max=F[i-1][j]。如果循环到了a[i]==b[j]的时候,则令F[i][j]=max+1。
最后答案是F[len(a)][1]..F[len(a)][len(b)]的最大值
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std; int a[],b[];
int ss[];
int dp[][];
int LCIS(int n,int m)
{
int k;
int sum=;
for(int i=;i<=n;i++)
{
k=;
for(int j=;j<=m;j++)
{
dp[i][j]=dp[i-][j];
if(a[i]==b[j])
//ss[j]=k+1;
dp[i][j]=k+;
else if(a[i]>b[j])
{
//if(k<ss[j])
// k=ss[j];
if(k<dp[i-][j])
k=dp[i-][j];
}
}
}
for(int i=;i<=m;i++)
//sum=max(sum,ss[i]);
if(sum<dp[n][i])
sum=dp[n][i]; return sum;
}
int main()
{
int t,n,m,ans;
scanf("%d",&t);
while(t--)
{
memset(ss,,sizeof(ss));
scanf("%d",&n);
for(int i=;i<=n;i++)
scanf("%d",&a[i]);
scanf("%d",&m);
for(int i=;i<=m;i++)
scanf("%d",&b[i]);
ans=LCIS(n,m);
printf("%d\n",ans);
if(t)
printf("\n");
} }
hdu 1423 最长公共递增子序列 LCIS的更多相关文章
- hdu 1423 最长公共递增子序列
这题一开始把我给坑了,我还没知道LCIS的算法,然后就慢慢搞吧,幸运的是还真写出来了,只不过麻烦了一点. 我是将该题转换为多条线段相交,然后找出最多多少条不相交,并且其数值死递增的. 代码如下: #i ...
- [ACM_动态规划] UVA 12511 Virus [最长公共递增子序列 LCIS 动态规划]
Virus We have a log file, which is a sequence of recorded events. Naturally, the timestamps are s ...
- hdu 1423 最长上升递增子序列
#include <iostream> #include <cstdio> #include <cstring> using namespace std; ; in ...
- 最长公共上升子序列(LCIS)
最长公共上升子序列慕名而知是两个字符串a,b的最长公共递增序列,不一定非得是连续的.刚开始看到的时候想的是先用求最长公共子序列,然后再从其中找到最长递增子序列,可是仔细想一想觉得这样有点不妥,然后从网 ...
- HDU 4512 最长公共上升子序列
各种序列复习: (1)最长上升子序列. 1.这个问题用动态规划就很好解决了,设dp[i]是以第i个数字结尾的上升子序列的最长长度.那么方程可以是dp[i]=max(dp[j]+1).(j<i). ...
- 动态规划——最长公共上升子序列LCIS
问题 给定两个序列A和B,序列的子序列是指按照索引逐渐增加的顺序,从原序列中取出若干个数形成的一个子集,若子序列的数值大小是逐渐递增的则为上升子序列,若A和B取出的两个子序列A1和B1是相同的,则A1 ...
- HDU 1423 最长公共字串+上升子序列
http://acm.hdu.edu.cn/showproblem.php?pid=1423 在前一道题的基础上多了一次筛选 要选出一个最长的递增数列 lower_bound()函数很好用,二分搜索找 ...
- HDU1423 最长公共上升子序列LCIS
Problem Description This is a problem from ZOJ 2432.To make it easyer,you just need output the lengt ...
- LCIS最长公共上升子序列
最长公共上升子序列LCIS,如字面意思,就是在对于两个数列A和B的最长的单调递增的公共子序列. 这道题目是LCS和LIS的综合. 在LIS中,我们通过两重循环枚举当序列以当前位置为结尾时,A序列中当前 ...
随机推荐
- swift语言点评二十一-协议
定义有什么,及哪些必须实现. A protocol defines a blueprint of methods, properties, and other requirements that su ...
- C# 打开文件 保存文件
string path = @"C: \Users\users\Desktop\xxxx.txt";// 文件路径 FileStream filestream = new File ...
- DataTable相关操作,筛选,取前N条数据,去重复行,获取指定列数据
#region DataTable筛选,排序返回符合条件行组成的新DataTable或直接用DefaultView按条件返回 /// <summary> /// Dat ...
- scrapy框架学习
一.初窥Scrapy Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中. 其最初是为了 页面抓取 (更确切来说, 网 ...
- selenium自动化(二).........................................Demo篇
二 编写简单代码 简单代码一: demo1.py 1.from selenium import webdriver driver = webdriver.Chrome() driver.get(& ...
- sudo不用在输入密码
在任意的路径之下执行:sudo visudo 的命令对文件进行修改: 其中的: sudo ALL=(ALL) %admin ALL=(ALL) 这两个语句为: sudo ALL=(ALL) NOPAS ...
- LAMP环境搭建备忘 -- Apache、pHp 安装 (二)
上一篇 Linux 已经安装好了,我们选择了 CentOS 7 的最小化安装,即没有图形界面,并且我们在安装时设置了网络连接即能够连上外部网络,还设置了 root 密码.下面我们要在此基础上继续安装 ...
- openssh 升级到7.5p1
1. 参照: http://www.cnblogs.com/xiegj/p/5669800.html http://blog.csdn.net/u011080082/article/details/5 ...
- Objective-C对象与Core Foundation对象
Core Foundation 对象主要使用在用C语言编写的Core Foundation 框架中,并引用计数的对象.与Objective-C对象差别非常少.不管哪种框架生成的对象,一旦生成,便可在两 ...
- HDU 3652 B-number(数位dp&记忆化搜索)
题目链接:[kuangbin带你飞]专题十五 数位DP G - B-number 题意 求1-n的范围里含有13且能被13整除的数字的个数. 思路 首先,了解这样一个式子:a%m == ((b%m)* ...