UVA - 11081 Strings 三个三维DP

题目大意:给出三个字符串,要求你用前两个字符串拼成第三个字符串,拼的规则是可以截取两个字符串的任意子串,然后再进行组装,问有多少种拼法

解题思路:参考了别人的思路,设置三个数组dp,dp1,dp2,这三个数组都是三维的。

dp[i][j][k]表示用第一串的前i个和第二串的前j个拼成了长度为k的字符串有多少种方法

dp1[i][j][k]表示用第一串的前i个和第二串的前j个拼成了长度为k的字符串有多少种方法,但最后一个字符是用第一个字符串的字符表示的

dp2的数组表示和dp1的相似,只不过最后一个字符是用第二串的字符表示的

这样一来的话,dp[i][j][k] = dp1[i][j][k] + dp2[i][j][k].

接着推dp1和dp2,因为两个相似,这里就只讲dp1

dp1[i][j][k] = dp[i-1][j][k]这是初始状态,接下来有两种情况

1.  str1[i] == str3[k],那么dp1[i][j][k] += dp[i-1][j][k-1],这里用的是dp,为什么是dp,因为要用第一串的最后一个当第三串的第k个字符了,所以已经不在乎第k-1个是哪个字符串的了。

2.不等的情况,那么就保持原样就可以了

#include<cstdio>
#include<cstring>
#define mod 10007
#define maxn 70
int dp1[maxn][maxn][maxn], dp2[maxn][maxn][maxn], dp[maxn][maxn][maxn];
char str1[maxn], str2[maxn], str3[maxn];
void solve() {

	int len1 = strlen(str1 + 1);
	int len2 = strlen(str2 + 1);
	int len3 = strlen(str3 + 1);

	memset(dp,0,sizeof(dp));
	memset(dp1,0,sizeof(dp1));
	memset(dp2,0,sizeof(dp2));

	for(int i = 0; i <= len1; i++)
		for(int j = 0; j <= len2; j++)
			dp[i][j][0] = dp1[i][j][0] = dp2[i][j][0] = 1;

	for(int k = 1; k <= len3; k++)
		for(int i = 0; i <= len1; i++)
			for(int j = 0; j <= len2; j++) {
				if(i) {
					dp1[i][j][k] = dp1[i-1][j][k];
					if(str1[i] == str3[k]) 
						dp1[i][j][k] += dp[i-1][j][k-1];
					dp1[i][j][k] %= mod;
				}
				if(j) {
					dp2[i][j][k] = dp2[i][j-1][k];
					if(str2[j] == str3[k]) 
						dp2[i][j][k] += dp[i][j-1][k-1];
					dp2[i][j][k] %=	 mod;
				}	
				dp[i][j][k] = (dp1[i][j][k] + dp2[i][j][k] ) % mod;
			}
	printf("%d\n",dp[len1][len2][len3]);
}

int main() {
	int test;
	scanf("%d",&test);
	while(test--) {
		scanf("%s%s%s",str1+1,str2+1,str3+1);
		solve();
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值