最长公共子序列(动态规划)

题目描述:

最长公共子序列问题:若给定序列X={x1,x2,…,xm},则另一序列Z={z1,z2,…,zk},是X的子序列是指存在一个严格递增下标序列{i1,i2,…,ik}使得对于所有j=1,2,…,k有:zj=xij。例如,序列Z={B,C,D,B}是序列X={A,B,C,B,D,A,B}的子序列,相应的递增下标序列为{2,3,5,7}。

给定2个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列。

给定2个序列X={x1,x2,…,xm}和Y={y1,y2,…,yn},找出X和Y的最长公共子序列。

输入数据:输入包括多组测试数据。每组数据包括一行,给出两个长度不超过200的字符串,表示两个序列。两个字符串之间由若干个空格隔开。

输出要求:对每组输入数据,输出一行,给出两个序列的最大公共子序列的长度。

源程序:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

#define MAX_LEN 1000
char str1[MAX_LEN];
char str2[MAX_LEN];
int maxLen[MAX_LEN][MAX_LEN];

int main()
{
	while(scanf("%s%s",str1+1,str2+1)>0)   //str1+1是指从str[1]开始存输入的字符 
	{
		int length1=strlen(str1+1);
		int length2=strlen(str2+1);
		int tmp;
		
		for(int i=0;i<=length1;i++)
			maxLen[i][0]=0;
		for(int i=0;i<=length2;i++)
			maxLen[0][i]=0;
		for(int i=1;i<=length1;i++)
		{
			for(int j=1;j<=length2;j++)
			{
				if(str1[i]==str2[j])
					maxLen[i][j]=maxLen[i-1][j-1]+1;
				else{
					int len1=maxLen[i][j-1];
					int len2=maxLen[i-1][j];
					if(len1>len2)
						maxLen[i][j]=len1;
					else
						maxLen[i][j]=len2;
				}
			} 
		}
		printf("%d\n",maxLen[length1][length2]);
	}
	return 0;
} 

   

下面这个还可以输出公共序列:

 #include<iostream>
 #include<cstdio>
 using namespace std;
 
 int c[100][100],b[100][100];
 char x[100],y[100];
 
 void LCSLength (int m, int n)
{
       int i ,j;
       for (i = 1; i <= m; i++) c[i][0] = 0;
       for (i = 1; i <= n; i++) c[0][i] = 0;
       for (i = 1; i <=m; i++)
          for (j = 1; j <=n; j++)
          {
            if (x[i]==y[j])
            {
                 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;
            }
         }
}
void LCS(int i ,int j)
{
      if (i ==0 || j==0) return;
      if (b[i][j]== 1)
      {
           LCS(i-1,j-1);
           printf("%c",x[i]);
      }
      else if (b[i][j]== 2)
           LCS(i-1,j);
      else LCS(i,j-1);
}

int main()
{
	int m,n;
	cin>>m>>n;
	for(int i=1;i<=m;i++)
		cin>>x[i];
	for(int i=1;i<=n;i++)
		cin>>y[i];
	cout<<endl;
	LCSLength(m,n);
	cout<<"最长公共子序列为:"; 
	LCS(m,n);
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值