Dynamic Programming(DP)之LCS(Longest Common Subsequence)/最长公共子序列

Posted hazel-wu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Dynamic Programming(DP)之LCS(Longest Common Subsequence)/最长公共子序列相关的知识,希望对你有一定的参考价值。

问题描述:

最长公共子序列。给定两个长度分别为M和N的字符串a和b,求既是a的子序列又是b的子序列的字符串长度最长是多少。

状态表示:

f[i][j]表示前缀字串a[1~i]与b[1~j]的“最长公共子序列”的长度。

阶段划分:

已经处理的前缀长度(两个字符串中的位置,即一个二维坐标系)

转移方程:

f[i,j]=maxf[i-1,j],fg[i,j-1]  a[i]!=b[j]

f[i,j]=maxf[i-1,j],f[i,j-1],f[i-1,j-1]+1  a[i]=b[j]

边界:

f[i,0]=f[0,j]=0

目标:

f[M,N]

代码实现1:

#include<bits/stdc++.h>
using namespace std;
string a;
string b;
int s[1111][1111];
int main()
	cin>>a>>b;
	int x=a.size();
	int y=b.size();
	for(int i=1;i<=x;i++)
		for(int j=1;j<=y;j++)
			if(a[i-1]==b[j-1])
				s[i][j]=max(s[i][j],s[i-1][j-1]+1);
			else
				s[i][j]=max(s[i][j-1],s[i-1][j]);
			
		
	
	cout<<s[x][y];
	return 0;

在以下代码中,g[i,j]表示从哪里转移

代码实现2(打印路径):

写一个函数,用于递归输出

#include<bits/stdc++.h>
using namespace std;
char a[1111],b[1111];
int f[1111][1111];
int g[1111][1111];
void s(int i,int j)
	if(i==0||j==0)
		return;
	
	if(!g[i][j])
		s(i-1,j-1);
		cout<<a[i-1];
	else if(g[i][j]==1)
		s(i-1,j);
	else if(g[i][j]=-1)
		s(i,j-1);
	

int main()
	cin>>a>>b;
	int lena=strlen(a);
	int lenb=strlen(b);
	for(int i=1;i<=lena;i++)
		for(int j=1;j<=lenb;j++)
			if(a[i-1]==b[j-1])
				f[i][j]=f[i-1][j-1]+1;
				g[i][j]=0;
			else
				if(f[i-1][j]>f[i][j-1])
					f[i][j]=f[i-1][j];
					g[i][j]=1;
				else
					f[i][j]=f[i][j-1];
					g[i][j]=-1;
				
			
		
	
	s(lena,lenb);
	return 0;

代码实现3(打印路径):

逆序的回溯,使用栈存储路径

#include<bits/stdc++.h>
using namespace std;
char a[1111],b[1111],c;
int f[1111][1111];
int main()
	cin>>a>>b;
	int la=strlen(a);
	int lb=strlen(b);
	for(int i=1;i<=la;i++)
		for(int j=1;j<=lb;j++)
			if(a[i-1]==b[j-1])
				f[i][j]=f[i-1][j-1]+1;
			else
				f[i][j]=max(f[i-1][j],f[i][j-1]);
			
		
	
	int i=la,j=lb;
	stack<char>s;
	while(f[i][j])
		if(f[i][j]==f[i-1][j])
			i--;
		else if(f[i][j]==f[i][j-1])
			j--;
		else if(f[i][j]>f[i-1][j-1])
			i--;
			j--;
			s.push(a[i]);
		
	
	while(!s.empty())
		c=s.top();
		cout<<c;
		s.pop();
	
	return 0;

以上是关于Dynamic Programming(DP)之LCS(Longest Common Subsequence)/最长公共子序列的主要内容,如果未能解决你的问题,请参考以下文章

动态规划算法(Dynamic Programming,简称 DP)

2017 UESTC Training for Dynamic Programming

动态规划-Dynamic Programming(DP)

LeetCode-easy-Maximum Subarray (DP:Dynamic Programming)

动态规划(Dynamic Programming)总结

leetcode-mid-dynamic programming- Longest Increasing Subsequence-NO