额、、失误、、

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. 从两个集合里排除重复的写法(适用:DB表和字段都很多,表间有关联的情况)

    获取其中一张表bulletinred为1的内容: public IList<BRShow> GetBulInfo() { var result = from a in ((Entities ...

  2. iOS afnetworking最新版报错 没有AFHTTPRequestOperationManager类了

    今天开了一个小项目   用的是pod   然后  安装好 Afnetworking之后   发现 AFHTTPRequestOperationManager  这个类没有了  ,百度之后  发现 原来 ...

  3. 如何在Angular2中使用Forms

    在Angular2中形成两个基本对象是Control和ControlGroup. 控制用户输入 Control 一个控制表示一个输入字段(ngFormControl) 一个控制可以绑定到一个input ...

  4. 08_一个java.lang.NullPointException报错

    [报错代码] public class UserDaoTest{ private SqlSessionFactory sqlSessionFactory; //此方法在执行testFindUserBy ...

  5. OpenCV(2)-Mat数据结构及访问Mat中像素

    Mat数据结构 一开始OpenCV是基于C语言的,在比较早的教材例如<学习OpenCV>中,讲解的存储图像的数据结构还是IplImage,这样需要手动管理内存.现在存储图像的基本数据结构是 ...

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

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

  7. JS当前日期相加相减

    function DateAddORSub(interval,type,number) { /* * 功能:实现Script的Date加减功能. * 参数:interval,字符串表达式,表示要添加的 ...

  8. 解决IE6下不支持 png24的透明图片问题

    常用的两种解决方案: 第一:使用IE滤镜解决 关键代码: css代码  _background:none;_filter:progid:DXImageTransform.Microsoft.Alpha ...

  9. 例行性工作排程 (crontab)

    1. 什么是例行性工作排程 1.1 Linux 工作排程的种类: at, crontab 1.2 Linux 上常见的例行性工作2. 仅运行一次的工作排程 2.1 atd 的启动与 at 运行的方式: ...

  10. POJ 1716 Integer Intervals 差分约束

    题目:http://poj.org/problem?id=1716 #include <stdio.h> #include <string.h> #include <ve ...