「题解」蝙蝠侠的麻烦

2 篇文章 0 订阅
这篇博客详细介绍了如何利用动态规划解决一个涉及三字符串的最长公共子序列问题。作者首先解析了题意,确定这是一个线性动态规划的最长公共子序列(LCS)问题,然后阐述了解题步骤,包括状态定义和状态转移方程。通过三层循环实现代码,最终找到了所有字符串中的最长公共子序列长度。
摘要由CSDN通过智能技术生成

没 事 找 事

「我的做题历程」:

step1:观察题面。

  「蝙蝠侠需要找到一个最长的字符串,使得这个字符串作为一个子序列被包含在所有的三个字符串中」,可以得出这是一道最长公共子序列,而且有三个字符串。(题型:线性 dp —— 最长公共子序列)
  「蝙蝠侠现在需要找到的是最大的长度,而不是序列」,说明只是一道普通的 LCS。


step2:思考解法。

  第一步思考 dp 状态:

d p i , j , k dp_{i,j,k} dpi,j,k:第一串前 i i i 项,第二串前 j j j 项,第三串前 k k k 项中的最长公共子序列长度。

  对于当前的 a i , b j , c k a_{i}, b_{j}, c_{k} ai,bj,ck 而言,只有能做贡献或无法做贡献两种状态。
  若 a i = b j = c k a_{i}= b_{j}= c_{k} ai=bj=ck,则它们能做贡献,此时的最长公共子序列的长度为第一串前 i − 1 i - 1 i1 项,第二串前 j − 1 j - 1 j1 项,第三串前 k − 1 k - 1 k1 项中的最长公共子序列的长度加 1 1 1
  否则它们无法做贡献,此时放弃做贡献最小的那一项。

  第二步思考状态转移方程:
  本题比常规的 LCS 要多一个字符串,因此只需要再多一维就好。
d p i , j , k = d p i − 1 , j − 1 , k − 1 + 1   ( a i = b j = c k ) dp_{i, j, k} = dp_{i - 1, j - 1 ,k - 1} + 1\ (a_{i} = b_{j} = c_{k}) dpi,j,k=dpi1,j1,k1+1 (ai=bj=ck)
d p i , j , k = max ⁡ { d p i − 1 , j , k , d p i , j − 1 , k , d p i , j , k − 1 }   ( a i ≠ b j  or  b j ≠ c k  or  a i ≠ c k ) dp_{i, j, k} = \max\{dp_{i - 1, j ,k},dp_{i, j - 1 ,k},dp_{i, j ,k - 1}\} \ (a_{i} \ne b_{j} \text{ or } b_{j} \ne c_{k} \text{ or }a_{i} \ne c_{k}) dpi,j,k=max{dpi1,j,k,dpi,j1,k,dpi,j,k1} (ai=bj or bj=ck or ai=ck)


step3:完成代码:

  因为有三个字符串,所以需要比平常的 LCS 多一层循环。

代码(抵制学术不端行为,拒绝 Ctrl + C):
#include <bits/stdc++.h>
using namespace std;
const int N = 5e1 + 5; 
char a[N], b[N], c[N];
int la, lb, lc, dp[N][N][N];
/* 
dp(i, j, k): 前 i, j, k 项中的最长公共子序列 
if a(i) = b(j) = c(k)
	dp(i, j, k) = dp(i - 1, j - 1, k - 1) + 1;
else 
	dp(i, j, k) = max{dp(i - 1, j, k), dp(i, j - 1, k), dp(i, j, k - 1)};
*/ 
int main() {
	freopen("trouble.in", "r", stdin);
	freopen("trouble.out", "w", stdout);
	scanf("%s\n%s\n%s", a + 1, b + 1, c + 1);
	la = strlen(a + 1), lb = strlen(b + 1), lc = strlen(c + 1);
	for (int i = 1; i <= la; i++) {
		for (int j = 1; j <= lb; j++) {
			for (int k = 1; k <= lc; k++) {
				if (a[i] == b[j] && b[j] == c[k]) {
					dp[i][j][k] = dp[i - 1][j - 1][k - 1] + 1;
				} else {
					dp[i][j][k] = max(dp[i - 1][j][k], max(dp[i][j - 1][k], dp[i][j][k - 1]));
				}
			}
		}
	}
	printf("%d", dp[la][lb][lc]);
	return 0;
} 

Trouble is a friend, but Accepted is better than it!


让我们来解决 『蝙蝠侠的麻烦』 叭~

Bye bye!!1 👋👋

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值