额、、失误、、

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. mysql更改root密码及root远程登录

    1.更改root密码 use mysql; update user set password=password('petecc') where user='root'; 2.root远程登录 1 up ...

  2. iOS zipzap读取压缩文件

    最近在公司遇到一项需求,在不解压zip文件的情况下读取其中的文件,因为之前使用的ziparchive不能满足现在的需求,所以在网上一阵狂搜,终于找到了zipzap,实话说还真的难找. 之前读取本地zi ...

  3. Oracle 10g 默认安装带来的用户名/密码

    ORACLE数据库创建的时候,创建了一系列默认的用户和表空间 Oracle 10g 默认安装带来的用户名/密码 Username Password Description See Also CTXSY ...

  4. iTerm 使用expect实现自动远程登录,登录跳板机

    #!/usr/bin/expect set timeout 10 spawn ssh -p [lindex $argv 0] [lindex $argv 1]@[lindex $argv 2] exp ...

  5. python 自动化之路 day 02

    本节内容: 列表.元组操作 字符串操作 1. 列表.元组操作 列表是我们最以后最常用的数据类型之一,通过列表可以对数据实现最方便的存储.修改等操作 定义列表 1 names = ['Alex',&qu ...

  6. 【转】PHP网站常见安全漏洞,及相应防范措施总结

    ---恢复内容开始--- 目前,基于PHP的网站开发已经成为目前网站开发的主流,本文笔者重点从PHP网站攻击与安全防范方面进行探究,旨在减少网站漏洞,希望对大家有所帮助! 一.常见PHP网站安全漏洞 ...

  7. 网站前端优化 -saveForSelf

    九.网站前端优化 – IMG 9.1.可以优化的图片 图片总共可以分为两类,一个是CSS IMAGES,另一个是产品图片. 9.2.CSS IMAGES CSS图片现在采用的方式是图片合并的方式,这样 ...

  8. .NET异步操作学习之一:Async/Await中异常的处理

    以前的异常处理,习惯了过程式的把出现的异常全部捕捉一遍,然后再进行处理.Async/Await关键字出来之后的确简化了异步编程,但也带来了一些问题.接下来自己将对这对关键字进行学习.然后把研究结果放在 ...

  9. 读取xml文件(可执行文件根目录debug)

    xml文件格式如下 <?xml version="1.0" encoding="utf-8" ?> <root> <appKey& ...

  10. PHP程序实现利用rand(1,100)函数产生10个1~100之间的随机数

    //echo rand(1,100);$max=0;$min=100;for($i=0;$i<=9;$i++){ $rand[$i]=rand(1,100); if($rand[$i]>$ ...