来自今天的算法作业

动态规划——最长公共子序列

最长公共子序列(LCS)是一个在一个序列集合中(通常为两个序列)用来查找所有序列中最长子序列的问题(子序列不需要在原序列中占用连续的位置)。

#include <bits/stdc++.h>
using namespace std;
void LCS(int i,int j,char *str1,int **b){
	if(i==0||j==0)
		return ;
	if(b[i][j]==1){
		LCS(i-1,j-1,str1,b);
		cout<<str1[i-1];		//c中的第i行元素对应str1的第i-1个元素
	}	
	else if(b[i][j]==2){
		LCS(i-1,j,str1,b);
	}
	else
		LCS(i,j-1,str1,b);
}
int main()
{
	char str1[101],str2[101];
	int c[101][101],i,j;
	cout<<"请输入第一个字符串:"<<endl;
	gets(str1);
	cout<<"请输入第二个字符串:"<<endl;
	gets(str2);
	int n=strlen(str1);
	int m=strlen(str2);
	int **b=new int*[n+1];  
    for(i=0;i<=n;i++)  
        b[i]=new int[m+1]; 
	for(i=0;i<=n;i++)	//将表中第0列初始化为0 
		c[i][0]=0;
	for(j=0;j<=m;j++)	//将表中第0行初始化为0	
		c[0][j]=0;	 
	for(i=1;i<=n;i++){
		for(j=1;j<=m;j++){
			if(str1[i-1]==str2[j-1]){
				c[i][j]=c[i-1][j-1]+1;
				b[i][j]=1;
			}
			else if(c[i-1][j]>=c[i][j-1]){
				c[i][j]=c[i-1][j];
				b[i][j]=2;
			}
			else{
				c[i][j]=c[i][j-1];
				b[i][j]=3;
			}
		}
	}	
	cout<<"最长公共子序列长度为:"<<c[n][m]<<endl;
	cout<<"此子序列为:";
	LCS(n,m,str1,b); 
	return 0;	
} 


此次的作业中有一个小地方弄了很久。就是c[][]这个二维数组的0行0列都是直接置0的,从c[][]数组第1行第1列的开始才是有用的,而str1和str2两个字符串数组都是从0开始的,那么c数组第i行的元素其实对应的是str的i-1个元素。所以在写的时候有两处:输出子序列时和判断两个序列元素相等时都要注意!

此算法的时间复杂度为O(nm)