#include <iostream>
#include <string>
using namespace std;
/*
最长公共子序列LCS
证明最优子结构
input: Xm,Yn
output: Zk
1.分析最优解的结构,即原问题的最优解包含了子问题的最优解
设X和Y的LCS为Z,则最优解max为Z
子问题分三种情况
1)若Xm=Yn,则Zk=Xm=Yn,Zk-1是Xm-1和Yn-1的LCS
反证:假设Xm-1和Yn-1的LCS不是Zk-1而是W,那么Zk-1<W,Zk-1∪{Zk}<Zw∪{Zk},与Zk是最优解矛盾
2)若Xm!=Yn,且Xm!=Zk,则Z是Xm-1和Yn的LCS。
反证:假设Xm-1和Y的LCS不是Zk-1,与最优解Zk矛盾
3)若Xm!=Yn,且Yn!=Zk,则Z是Xm和Yn-1的LCS。
反证: 同(2)
2.状态转移方程(state transition)
C(i,j)= (1) C(i-1,j-1)+1 Xi=Yj
(2) max{C(i-1,j),C(i,j-1)} Xi!=Yj
//初始状态
第一行,第一列都为0,当做辅助空间,方便存储
求的是结果C(m,n),从低到上,用二维DP保存结果
*/
int LCS(string s1,string s2){
int m = s1.size(),n=s2.size();
int dp[m+1][n+1];
//初始化
int i,j;
for(i=0;i<=m;i++)
dp[i][0] = 0;
for(j=0;j<=n;j++)
dp[0][j] = 0;
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
if(s1[i-1]==s2[j-1]){ //Xi=Yj
dp[i][j] = dp[i-1][j-1] +1;
}else{
dp[i][j] = dp[i-1][j]>dp[i][j-1]?dp[i-1][j]:dp[i][j-1]; //取max放进去
}
}
}
for(int i=0;i<=m;i++){
for(int j=0;j<=n;j++){
cout<<dp[i][j]<<" ";
}
cout<<endl;
}
//空间可以压缩 从m行压缩到两行
//打印序列,深度优先直接追溯回去
//可以搞个栈或者单链表的头插法
i=m,j=n;
string Stack;
while(dp[i][j]!=0){
if(dp[i][j]==dp[i-1][j]){//往上走
i--;
}else if(dp[i][j]==dp[i][j-1]){ //上走不了往左走
j--;
}else{ //两边都走不了
Stack.push_back(s1[i-1]);
i--,j--;
}
}
for(i=Stack.size()-1;i>=0;i--){
cout<<Stack[i];
}
}
int main(){
string s1 = "qwfhkl";
string s2 = "wrhiq";
LCS(s1,s2);
return 0;
}
02-21
“相关推荐”对你有帮助么?
-
非常没帮助
-
没帮助
-
一般
-
有帮助
-
非常有帮助
提交