uva10723(dp 最长公共子序列)

题目的意思就是给你两个串,然后你构造一个串,使这两个串都是它的子串.并且这个串要最短.

问最短多长,还有构造成最短长度的方法有几种.


首先我们可以知道,如果把两个串合并成一个串,肯定是可以满足条件的,但是不是最短的..

而且如果是两个串的公共子序列,那么就可以只算一遍.

所以最短应该是两个串长度的和,减掉两个串的最长公共子序列的长度.


接下来是有几种方法.

我们可以在算最长公共子序列的时候一起算.

如果str1[i] != str2[j]那么公共子序列d[i][j] = max { d[i - 1][j], d[i][j - 1]};

如果是d[i - 1][j]大,说明这个串就能多出f[i - 1][j]种,就是这时候最长的那串是str1[i - 1],str2[j]结束的.

反之则反...但是如果d[i - 1][j]和d[i][j - 1]相等,就两个都加上去.


AC代码:


#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;

const int N = 35;
ll f[N][N];
int d[N][N];
char str1[N];
char str2[N];
int n1,n2;

int main() {
	int cas = 1;
	int t;
	scanf("%d",&t);
	getchar();
	while(t--) {
		memset(f , 0 ,sizeof(f));
		memset(d , 0 ,sizeof(d));
		gets(str1 + 1);
		gets(str2 + 1);
		n1 = strlen(str1 + 1);
		n2 = strlen(str2 + 1);
		for (int i = 0 ; i < N ; i++) {
			f[i][0] = f[0][i] = 1;
		}
		for (int i = 1 ; i <= n1 ; i++) {
			for (int j = 1 ; j <= n2 ;j++) {
				if(str1[i] == str2[j]) {
					d[i][j] = d[i - 1][j - 1] + 1;
					f[i][j] += f[i - 1][j - 1];
				}
				else {
					d[i][j] = max(d[i - 1][j] , d[i][j - 1]);
					if(d[i - 1][j] > d[i][j - 1])
						f[i][j] += f[i - 1][j];
					else if(d[i][j - 1] > d[i - 1][j])
						f[i][j] += f[i][j - 1];
					else
						f[i][j] += (f[i - 1][j] + f[i][j - 1]);
				}
			}
		}
		printf("Case #%d: %d %lld\n",cas++ ,n1 + n2 - d[n1][n2] , f[n1][n2]);
	}
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值