额、、失误、、

LCS是Longest Common Subsequence的缩写,即最长公共子序列。一个序列,如果是两个或多个已知序列的子序列,且是所有子序列中最长的,则为最长公共子序列。

DP、O(n^2)解法:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define max(a,b) ((a)>(b)?(a):(b))
#define N 1010 int p,q;
int a[N];
int b[N];
int dp[N][N]; void solve()
{
int i,j;
memset(dp,,sizeof(dp));
for(i=;i<=p;i++)
{
for(j=;j<=q;j++)
{
if(a[i]==b[j])
{
dp[i][j]=dp[i-][j-]+;
}
else
{
dp[i][j]=max(dp[i-][j],dp[i][j-]);
}
}
}
cout<<dp[p][q]<<endl;
}
int main()
{
int i;
while(scanf("%d%d",&p,&q)!=EOF)
{
for(i=;i<=p;i++)
{
scanf("%d",&a[i]);
}
for(i=;i<=q;i++)
{
scanf("%d",&b[i]);
}
solve();
}
return ;
}

O(nlogn)解法:

参考http://www.cs.ucf.edu/courses/cap5937/fall2004/Longest%20common%20subsequence.pdf

最长公共子序列 的 nlogn 的算法本质是 将该问题转化成 最长增序列(LIS),因为 LIS 可以用nlogn实现,所以求LCS的时间复杂度降低为 nlogn。

转化:将LCS问题转化成LIS问题。

               假设有两个序列 s1[ 1~6 ] = { a, b, c , a, d, c }, s2[ 1~7 ] = { c, a, b, e, d, a, b }。

记录s1中每个元素在s2中出现的位置, 再将位置按降序排列, 则上面的例子可表示为:

loc( a)= { 6, 2 }, loc( b ) = { 7, 3 }, loc( c ) = { 1 }, loc( d ) = { 5 }。

将s1中每个元素的位置按s1中元素的顺序排列成一个序列s3 = { 6, 2, 7, 3, 1, 6, 2, 5, 1 }。

在对s3求LIS得到的值即为求LCS的答案。(这点我也只是大致理解,读者可以自己理解甚至证明。)

上面一段话转载自:http://blog.csdn.net/non_cease/article/details/6918848

1、当无重复元素时:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define N 1010 int len;
int p,q;
int a[N];
int b[N];
int dp[N]; void convert()
{
int i,hash[N]={};
for(i=;i<=p;i++)
{
hash[a[i]]=i;
}
for(i=;i<=q;i++)
{
b[i]=hash[b[i]];
}
}
int up_bound(int k)
{
int l=,r=len+;
while(l<r)
{
int m=(l+r)>>;
if(dp[m]<=k) l=m+;
else r=m;
}
return l;
}
void solve()
{
len=;
dp[]=-0x7ffffff;
for(int i=;i<=q;i++)
{
if(!b[i]) continue;
if(b[i]>dp[len]) dp[++len]=b[i];
else
{
int pos=up_bound(b[i]);
dp[pos]=b[i];
}
}
printf("%d\n",len);
}
int main()
{
while(scanf("%d%d",&p,&q)!=EOF)
{
for(int i=;i<=p;i++)
{
scanf("%d",&a[i]);
}
for(int i=;i<=q;i++)
{
scanf("%d",&b[i]);
}
convert();
solve();
}
return ;
}

2、当有重复元素时:

#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
#define N 10010 int n;
int p,q;
int len;
int a[N];
int b[N];
int s[N];
int dp[N]; void convert()
{
vector<int> v[N];
for(int i=;i<=p;i++)
{
v[a[i]].push_back(i);
}
n=;
for(int i=;i<=q;i++)
{
for(int j=v[b[i]].size()-;j>=;j--)
{
s[++n]=v[b[i]][j];
}
}
}
int up_bound(int k)
{
int l=,r=len+;
while(l<r)
{
int m=(l+r)>>;
if(dp[m]<=k) l=m+;
else r=m;
}
return l;
} void solve()
{
len=;
dp[]=-0x7fffffff;
for(int i=;i<=n;i++)
{
if(s[i]>dp[len]) dp[++len]=s[i];
else
{
int pos=up_bound(s[i]-);
dp[pos]=s[i];
}
}
printf("%d\n",len);
}
int main()
{
while(scanf("%d%d",&p,&q)!=EOF)
{
for(int i=;i<=p;i++)
{
scanf("%d",&a[i]);
}
for(int i=;i<=q;i++)
{
scanf("%d",&b[i]);
}
convert();
solve();
}
return ;
}

[DP] LCS小结的更多相关文章

  1. UVA.10192 Vacation (DP LCS)

    UVA.10192 Vacation (DP LCS) 题意分析 某人要指定旅游路线,父母分别给出了一系列城市的旅游顺序,求满足父母建议的最大的城市数量是多少. 对于父母的建议分别作为2个子串,对其做 ...

  2. UVA.10066 The Twin Towers (DP LCS)

    UVA.10066 The Twin Towers (DP LCS) 题意分析 有2座塔,分别由不同长度的石块组成.现在要求移走一些石块,使得这2座塔的高度相同,求高度最大是多少. 问题的实质可以转化 ...

  3. UVA-1625-Color Length(DP LCS变形)

    Color Length(UVA-1625)(DP LCS变形) 题目大意 输入两个长度分别为n,m(<5000)的颜色序列.要求按顺序合成同一个序列,即每次可以把一个序列开头的颜色放到新序列的 ...

  4. 插头$DP$学习小结

    插头\(DP\)学习小结 这种辣鸡毒瘤东西也能叫算法... 很优秀的一个算法. 最基本的适用范围主要是数据范围极小的网格图路径计数问题. 如果是像\(Noi2018\)那种的话建议考生在其他两道题难度 ...

  5. UVA 11404 Palindromic Subsequence[DP LCS 打印]

    UVA - 11404 Palindromic Subsequence 题意:一个字符串,删去0个或多个字符,输出字典序最小且最长的回文字符串 不要求路径区间DP都可以做 然而要字典序最小 倒过来求L ...

  6. LightOJ1033 Generating Palindromes(区间DP/LCS)

    题目要计算一个字符串最少添加几个字符使其成为回文串. 一年多前,我LCS这道经典DP例题看得还一知半解时遇到一样的问题,http://acm.fafu.edu.cn/problem.php?id=10 ...

  7. poj 1159 (DP LCS)

    滚动数组 + LCS // File Name: 1159.cpp // Author: Missa_Chen // Created Time: 2013年07月08日 星期一 10时07分13秒 # ...

  8. poj1080--Human Gene Functions(dp:LCS变形)

    Human Gene Functions Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 17206   Accepted:  ...

  9. UVA 531 - Compromise(dp + LCS打印路径)

      Compromise  In a few months the European Currency Union will become a reality. However, to join th ...

随机推荐

  1. Ext.Net学习笔记08:Ext.Net中使用数据

    之前的七篇文章都是介绍Ext.Net较为基础的东西,今天的这一篇将介绍数据的一些用法,包括XTemplate绑定数据.Store(Modal.Proxy).ComboBox的用法等. XTemplat ...

  2. 安装完oracle重新启动后报ORA-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务(重启前正常)

    安装完oracle重新启动后报ORA-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务(重启前正常) 刚安装完后用plSql登录正常. 在dos命令行下 输入  sqlplus 用户 ...

  3. asp.net:用类来后台绑定数据源

    //封装成一个 using System;using System.Collections.Generic;using System.Linq;using System.Web;using Syste ...

  4. Ibatis中sqlmap参数map中还需要套list的情况如何写?

    原始需求: 有若干个参数,需要作为ibatis拼装sql的参数传入,但是有个参数的值比较特殊,是若干种枚举值.具体到这个case,就是有有限个namespace.我每次需要通过传入多个namespac ...

  5. c++ primer复习(四)

    1 标准库容器 顺序容器:vector.list.deque 容器适配器:stack.queue.priority_queue 2 容器元素类型约束: 容器元素类型必须支持复制和赋值,因为容器存放的都 ...

  6. swift基本语法

    swift种语法着实怪异,实质干的事情还是一样的,一下将对此语法做简单介绍: 1.swift语法种已经剔除“:”这个结束符号,下面将演示入门操作的hello world import Foundati ...

  7. Android学习7--日志信息的使用

    在代码的调试中,日志信息是必不可少的,关于日志信息的使用,接下来,小编简要的说明一下: 日志分为几种:Verbose:从字面上解释,verbose为冗长的,啰嗦的,所以verbose日志信息输出的内容 ...

  8. html定义对象

    <object>定义一个对象<param>为对象定义一个参数 参数的名称:name = "" 参数的值:value=""classid: ...

  9. HTML5 的绘图支持- canvas

    Canvas HTML5新增了一个canvas元素,它是一张空画布,开发者需要通过JavaScript脚本进行绘制. 在canvas上绘图,经过如下3步 (1) 获取canvas元素对应的DOM对象. ...

  10. php中浮点数计算问题

    如果用php的+-*/计算浮点数的时候,可能会遇到一些计算结果错误的问题,比如echo intval( 0.58*100 );会打印57,而不是58,这个其实是计算机底层二进制无法精确表示浮点数的一个 ...