蝙蝠侠的难题解析是怎样的?

2026-05-25 05:301阅读0评论SEO资源
  • 内容介绍
  • 相关推荐

本文共计759个文字,预计阅读时间需要4分钟。

蝙蝠侠的难题解析是怎样的?

没 事 找 事

「我的做题历程」:

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


step2:思考解法。
  第一步思考 dp 状态:

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

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

  第二步思考状态转移方程:
  本题比常规的 LCS 要多一个字符串,因此只需要再多一维就好。

蝙蝠侠的难题解析是怎样的?

\[dp_{i, j, k} = dp_{i - 1, j - 1 ,k - 1} + 1\ (a_{i} = b_{j} = 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}) \]


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; }



让我们来解决 [『蝙蝠侠的麻烦』] 叭~(222.180.160.110:1024/problem/29415)

Bye bye!!1

本文共计759个文字,预计阅读时间需要4分钟。

蝙蝠侠的难题解析是怎样的?

没 事 找 事

「我的做题历程」:

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


step2:思考解法。
  第一步思考 dp 状态:

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

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

  第二步思考状态转移方程:
  本题比常规的 LCS 要多一个字符串,因此只需要再多一维就好。

蝙蝠侠的难题解析是怎样的?

\[dp_{i, j, k} = dp_{i - 1, j - 1 ,k - 1} + 1\ (a_{i} = b_{j} = 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}) \]


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; }



让我们来解决 [『蝙蝠侠的麻烦』] 叭~(222.180.160.110:1024/problem/29415)

Bye bye!!1