当前位置:网站首页>最长公共子序列(LCS)(动态规划,递归)
最长公共子序列(LCS)(动态规划,递归)
2022-07-06 23:08:00 【疯疯癫癫才自由】
1)从前往后递推:
- 状态设计:dp[i][j]表示两个序列从首位置开始,第一个序列到i-1位置, 第二个到j-1位置的最长公共子序列;
- 状态转移方程:dp[i][j]=dp[i-1][j-1]+1 (str1[i-1]==str2[j-1]);
- || = max(dp[i-1][j],dp[i][j-1]) (str1[i-1]!=str2[j-1]);
- 边界:dp[0][j]=dp[i]=0;(i=0...len1,j=0...len2);
- 最后可根据dp[i][j]的值输出最长公共子序列的内容,当dp[i][j]== (dp[i-1][j] || dp[i][j-1]时,明显str1[i]!=str[j];当dp[i][j]==dp[i-1][j-1]时,明显str1[i]==str2[j],那么就把这个元素加到 str中。
- 当然,如果从前往后递推,字符的下标是从1开始的,那么状态设计可以这么表示:状态设计:dp[i][j]表示两个序列从首位置开始,第一个序列到i位置,第二个到j位置的最长公共子序列;而我下面的 程序输入的字符下标是从0开始输入的。
/**
1)状态设计:dp[i][j]表示两个序列从首位置开始,第一个序列到i-1位置,
第二个到j-1位置的最长公共子序列;
状态转移方程:dp[i][j]=dp[i-1][j-1]+1 (str1[i-1]==str2[j-1]);
|| = max(dp[i-1][j],dp[i][j-1]) (str1[i-1]!=str2[j-1]);
边界:dp[0][j]=dp[i]=0;(i=0...len1,j=0...len2);
最后可根据dp[i][j]的值输出最长公共子序列的内容,当dp[i][j]==
(dp[i-1][j] || dp[i][j-1]时,明显str1[i]!=str[j];当dp[i][j]
==dp[i-1][j-1]时,明显str1[i]==str2[j],那么就把这个元素加到
str中。
当然,如果从前往后递推,字符的下标是从1开始的,那么状态设计
可以这么表示:状态设计:dp[i][j]表示两个序列从首位置开始,
第一个序列到i位置,第二个到j位置的最长公共子序列;而我下面的
程序输入的字符下标是从0开始输入的。
*/
/**
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
string str1,str2;
cout << "input two strings:\n";
cin >> str1 >> str2;
int len1=str1.size(),len2=str2.size();
int dp[len1+1][len2+1]; //dp[i][j]表示两个序列从首位置开始,第一个序列到i-1位置,第二个到j-1位置
string str; //的最长公共子序列
for(int i=0;i<=len1;++i)
dp[i][0]=0;
for(int j=0;j<=len2;++j)
dp[0][j]=0;
for(int i=1;i<=len1;++i)
for(int j=1;j<=len2;++j)
{
if(str1[i-1]==str2[j-1])
dp[i][j]=dp[i-1][j-1]+1;
else
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
for(int i=len1,j=len2;i>0&&j>0;) //似乎又有two point 的影子
{
if(dp[i][j]==dp[i-1][j])
--i;
else if(dp[i][j]==dp[i][j-1])
--j;
else
{
str=str1[i-1]+str;
--i;
--j;
}
}
cout << dp[len1][len2] << endl;
cout << str << endl;
cout << "Hello world!" << endl;
return 0;
}
*/
2)从后往前推;
状态设计:dp[i][j]表示两个序列从尾位置开始,第一个序列到i位置,
第二个到j位置的最长公共子序列;
状态转移方程:dp[i][j]=dp[i+1][j+1]+1 (str1[i]==str2[j]);
|| = max(dp[i+1][j],dp[i][j+1]) (str1[i]!=str2[j]);
最后可根据dp[i][j]的值输出最长公共子序列的内容,当dp[i][j]==
(dp[i+1][j] || dp[i][j+1]时,明显str1[i]!=str[j];当dp[i][j]
==dp[i-1][j-1]时,明显str1[i]==str2[j]。
/**
2)从后往前推;
状态设计:dp[i][j]表示两个序列从尾位置开始,第一个序列到i位置,
第二个到j位置的最长公共子序列;
状态转移方程:dp[i][j]=dp[i+1][j+1]+1 (str1[i]==str2[j]);
|| = max(dp[i+1][j],dp[i][j+1]) (str1[i]!=str2[j]);
最后可根据dp[i][j]的值输出最长公共子序列的内容,当dp[i][j]==
(dp[i+1][j] || dp[i][j+1]时,明显str1[i]!=str[j];当dp[i][j]
==dp[i-1][j-1]时,明显str1[i]==str2[j]。
*/
/**
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
string str1,str2;
cout << "input two strings:\n";
cin >> str1 >> str2;
int len1=str1.size(),len2=str2.size();
int dp[len1+1][len2+1]={0}; //dp[i][j]表示两个序列从尾位置开始,第一个序列到i位置,第二个到j位置
string str; //的最长公共子序列
for(int i=0;i<=len1;++i)
dp[i][0]=0;
for(int j=0;j<=len2;++j)
dp[0][j]=0;
for(int i=len1-1;i>=0;--i)
for(int j=len2-1;j>=0;--j)
{
if(str1[i]==str2[j])
dp[i][j]=dp[i+1][j+1]+1;
else
dp[i][j]=max(dp[i+1][j],dp[i][j+1]);
}
for(int i=0,j=0;i<len1&&j<len2;) //似乎又有two point 的影子
{
if(dp[i][j]==dp[i+1][j])
++i;
else if(dp[i][j]==dp[i][j+1])
++j;
else
{
str+=str1[i];
++i;
++j;
}
}
cout << dp[0][0] << endl;
cout << str << endl;
cout << "Hello world!" << endl;
return 0;
}
*/
递归解决:
/**
3)递归解决
*/
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
string str1,str2,str;
int dp[100][100];
int lcs_len(int l1,int l2);
void lcs_str(int l1,int l2);
int main()
{
cout << "input two strings:\n";
cin >> str1 >> str2;
int len1=str1.size(),len2=str2.size();
memset(*dp,-1,sizeof dp);
lcs_len(len1,len2);
lcs_str(len1,len2);
cout << dp[len1][len2] << endl;
cout << str << endl;
cout << "Hello world!" << endl;
return 0;
}
int lcs_len(int l1,int l2)
{
if(dp[l1][l2]!=-1)
return dp[l1][l2];
else
{
if(l1==0||l2==0)
return dp[l1][l2]=0;
if(str1[l1-1]==str2[l2-1])
return dp[l1][l2]=lcs_len(l1-1,l2-1)+1;
else
return dp[l1][l2]=max(lcs_len(l1-1,l2),lcs_len(l1,l2-1));
}
}
void lcs_str(int l1,int l2)
{
if(l1==0||l2==0)
return ;
if(dp[l1][l2]==dp[l1-1][l2])
lcs_str(l1-1,l2);
else if(dp[l1][l2]==dp[l1][l2-1])
lcs_str(l1,l2-1);
else
{
str=str1[l1-1]+str;
lcs_str(l1-1,l2-1);
}
}
边栏推荐
- Tree map: tree view - draw covid-19 array diagram
- Leetcode(417)——太平洋大西洋水流问题
- JS also exports Excel
- Decorator basic learning 02
- Markdown编辑器
- 高数中值定理总结
- 《四》表单
- Local tool [Navicat] connects to remote [MySQL] operation
- JS variable case
- Flask project uses flask socketio exception: typeerror: function() argument 1 must be code, not str
猜你喜欢
随机推荐
使用Thread类和Runnable接口实现多线程的区别
A row of code r shows the table of Cox regression model
Weebly mobile website editor mobile browsing New Era
Mysql database (basic)
【PHP SPL笔记】
U++ metadata specifier learning notes
When knative meets webassembly
Salesforce 容器化 ISV 场景下的软件供应链安全落地实践
JDBC link Oracle reference code
Dynamically generate tables
offer如何选择该考虑哪些因素
JS variable
Leetcode notes
一个酷酷的“幽灵”控制台工具
Why do many people misunderstand technical debt
IMS data channel concept of 5g vonr+
为什么很多人对技术债务产生误解
高数中值定理总结
STM32F103ZE+SHT30检测环境温度与湿度(IIC模拟时序)
《五》表格