51 nod 1006 最长公共子序列Lcs
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1006
参考博客 :http://blog.csdn.net/yysdsyl/article/details/4226630
引进一个二维数组c[][],用c[i][j]记录X[i]与Y[j] 的LCS 的长度,b[i][j]记录c[i][j]是通过哪一个子问题的值求得的,以决定搜索的方向。
我们是自底向上进行递推计算,那么在计算c[i,j]之前,c[i-1][j-1],c[i-1][j]与c[i][j-1]均已计算出来。此时我们根据X[i] = Y[j]还是X[i] != Y[j],就可以计算出c[i][j]。
计算 LCS 复杂度 O(n*m).由于每次调用至少向上或向左(或向上向左同时)移动一步,故最多调用(m + n)次就会遇到i = 0或j = 0的情况,此时开始返回。返回时与递归调用时方向相反,步数相同,故打印输出算法时间复杂度为Θ(m + n)。
打印序列,非递归。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#define MAXN 1111
#define MAXM 222222
#define INF 1000000000
using namespace std; char s[MAXN],t[MAXN],res[MAXN];
int dp[MAXN][MAXN],flag[MAXN][MAXN]; void LCS(int n,int m)
{
memset(dp,,sizeof(dp));
memset(flag,,sizeof(flag));
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{
if(s[i-]==t[j-])
{
dp[i][j]=dp[i-][j-]+;
flag[i][j]=;
}
else if(dp[i][j-]>dp[i-][j])
{
dp[i][j]=dp[i][j-];
flag[i][j]=;
}
else
{
dp[i][j]=dp[i-][j];
flag[i][j]=;
}
}
//printf("%d\n",dp[n][m]);
} void getLCS(int n,int m)
{
int k=;
while(n>&&m>)
{
if(flag[n][m]==)
{
res[k++]=s[n-];
n--;
m--;
}
else if(flag[n][m]==) m--;
else if(flag[n][m]==) n--;
}
for(int i=k-;i>=;i--)
{
printf("%c",res[i]);
}
printf("\n");
} int main()
{
//freopen("a.txt","r",stdin);
scanf("%s %s",s,t);
//printf("%s %s\n",s,t);
int l1=strlen(s),l2=strlen(t);
LCS(l1,l2);
/*for(int i=0;i<=l1;i++)
{
for(int j=0;j<=l2;j++)
printf("%d ",flag[i][j]);
printf("\n");
}
printf("\n");*/
getLCS(l1,l2);
return ;
}
递归
#include<cstdio>
#include<cstring>
const int maxn=;
int dp[maxn][maxn],flag[maxn][maxn];
int n,m;
char s[maxn],t[maxn]; void LCS(int n,int m)
{
memset(dp,,sizeof(dp));
memset(flag,,sizeof(flag));
for(int i=;i<n;i++)
for(int j=;j<m;j++)
{
if(s[i]==t[j])
{
dp[i+][j+]=dp[i][j]+;
flag[i+][j+]=;
}
else if(dp[i+][j]>dp[i][j+])
{
dp[i+][j+]=dp[i+][j];
flag[i+][j+]=;
}
else
{
dp[i+][j+]=dp[i][j+];
flag[i+][j+]=;
}
}
// printf("%d\n",dp[n][m]);
} void printLCS(int n,int m)
{
if(n==||m==) return; if(flag[n][m]==)
{
printLCS(n-,m-);
printf("%c",s[n-]);
}
else if(flag[n][m]==) printLCS(n,m-);
else printLCS(n-,m);
}
int main()
{
//freopen("a.txt","r",stdin);
scanf("%s %s",s,t);
int l1=strlen(s),l2=strlen(t);
LCS(l1,l2);
printLCS(l1,l2);
return ;
}
下面这种是比较简洁的。去掉了标记数组。
#include<string>
#include<iostream>
using namespace std;
const int maxn = ; int dp[maxn][maxn]={};
string a,b; void LCS(int n,int m)
{
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
if(a[i-]==b[j-]) dp[i][j]=dp[i-][j-]+;
else dp[i][j]=max(dp[i][j-],dp[i-][j]);
} int main()
{
cin>>a>>b;
int l1=a.size(),l2=b.size();
LCS(l1,l2);
int len=dp[l1][l2];
string ans;
int i=l1,j=l2;
while(dp[i][j])
{
if(dp[i][j]==dp[i-][j]) i--;
else if(dp[i][j]==dp[i][j-]) j--;
else ans.push_back(a[i-]),i--,j--;
}
for(int i=len-;i>=;i--)
cout<<ans[i];
return ;
}
51 nod 1006 最长公共子序列Lcs的更多相关文章
- 51 Nod 1006 最长公共子序列(LCS & DP)
原题链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1006 题目分析: 首先先知道LCS问题,这有两种: Long ...
- 1006 最长公共子序列Lcs
1006 最长公共子序列Lcs 基准时间限制:1 秒 空间限制:131072 KB 给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的). 比如两个串为: abcicba abdks ...
- 51nod 1006 最长公共子序列Lcs 【LCS/打印path】
1006 最长公共子序列Lcs 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注 给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的). ...
- 51nod 1006 最长公共子序列Lcs(经典动态规划)
传送门 Description 给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的). 比如两个串为: abcicba abdkscab ab是两个串的子序列,abc也是 ...
- 【51NOD】1006 最长公共子序列Lcs(动态规划)
给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的). 比如两个串为: abcicba abdkscab ab是两个串的子序列,abc也是,abca也是,其中abca是这两个 ...
- 51Nod - 1006 最长公共子序列Lcs模板
给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的). 比如两个串为: abcicba abdkscab ab是两个串的子序列,abc也是,abca也是,其中abca是这 ...
- 51Nod 1006 最长公共子序列Lcs问题 模板题
给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的). 比如两个串为: abcicba abdkscab ab是两个串的子序列,abc也是,abca也是,其中abca是这两个 ...
- 51NOD 1006 最长公共子序列 Lcs 动态规划 DP 模板题 板子
给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的). 比如两个串为: abcicba abdkscab ab是两个串的子序列,abc也是,abca也是,其中abca是这两个字符串最 ...
- 【51NOD-0】1006 最长公共子序列Lcs
[算法]经典DP [题解]经典lcs,输出路径可以记录上一个有效节点就是有点麻烦. 因为开始时写法不太明确,打印结果时初始循环地方搞错了,后来修正写法时忘了改过来,调了好久. #include< ...
随机推荐
- bzoj 2141 线段树套平衡树
用树套树来解决这个问题,存储每个节点的数值是多少,然后交换 对于答案的变更可以讨论下,假设交换的是x,y位置的数x<=y 如果x=y || high[x]=high[y]则对答案没有影响 如果h ...
- zip&rar格式压缩包的解压缩
实际工作中例子: 首先需要引入两个jar包: 注意:支持压缩软件4.20及以上版本 (1)压缩包的解压: (2)压缩包的压缩打包 zip格式:
- [工作记录] Android OpenGL ES: non-square texture - continue
previous: [工作记录] Android OpenGL ES 2.0: square texture not supported on some device recently I found ...
- 使用命令行进行 VS单元测试 MSTest
测试 指定的方法 "D:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE\MSTest.exe" /test ...
- C编译错误解决方法
1.expected identifier before numeric constant 一般情况下是枚举类型中的某个变量已经被#define定义过一次了,在项目空间中搜索你枚举类型中的所有变量类型 ...
- 【补解体报告】topcoder 634 DIV 2
A:应该是道语文题,注意边界就好: B:开始考虑的太复杂,没能够完全提取题目的思维. 但还是A了!我愚蠢的做法:二分答案加暴力枚举, 枚举的时候是完全模拟的,比如每次取得时候都是从大到小的去取,最后统 ...
- nodejs的安装和配置
上次我们介绍了nodeJs入门的一些概念包括nodeJs.npm.express,这次我们介绍在linux的安装以及配置过程 目录: 1 如何在 Linux.Windows上通过包或包管理器安装 No ...
- ZOJ题目分类
ZOJ题目分类初学者题: 1001 1037 1048 1049 1051 1067 1115 1151 1201 1205 1216 1240 1241 1242 1251 1292 1331 13 ...
- poj 3228(二分+最大流)
题目链接:http://poj.org/problem?id=3228 思路:增设一个超级源点和一个超级汇点,源点与每一个gold相连,容量为gold数量,汇点与仓库相连,容量为仓库的容量,然后就是二 ...
- [转载]Jmeter那点事·ForEach和If控制器
如果我们要实现一个循环,如果城市是北京,则返回首都:否则,返回城市. 一.新建用户自定义变量 添加-配置元件-用户自定义变量, 定义变量注意命名格式:变量名 加 下划线 加 数字(从1开始计数) ...