豆包 LeetCode 1639.通过给定词典构造目标字符串的方案数 public int numWays(String[] words, String target)
选第 j 列(匹配 target[i-1]): dp[i][j] += dp[i-1][j-1] * cnt[j-1][c]2. DP 定义:-dp[i][j] :用前j列,拼出target前i个字符的方案数。// dp[i][j] = 前 j 列,拼 target 前 i 个字符的方案数。// 预处理:cnt[j][c] = 第 j 列字符 c 的出现次数。3. 转移:- 不选第 j 列: dp
下面我直接给你可直接提交的 Java 版标准题解,思路清晰、注释完整,对应 LeetCode 1639. Number of Ways to Form a Target String Given a Dictionary。
题目大意
- 给你一个字符串数组 words ,每个字符串长度相同。
- 你要按列选字符,拼成 target 。
- 选第 1 个字符必须在第 1 列,第 2 个字符必须在第 2 列,依此类推,列不能回头用。
- 求有多少种方案,答案对 1e9+7 取模。
思路(标准 DP)
1. 预处理:统计每一列,每个字符出现多少次。
2. DP 定义:- dp[i][j] :用前 j 列,拼出 target 前 i 个字符的方案数。
3. 转移:- 不选第 j 列: dp[i][j] += dp[i][j-1]
- 选第 j 列(匹配 target[i-1]): dp[i][j] += dp[i-1][j-1] * cnt[j-1][c]
4. 答案: dp[len(target)][len(words[0])]
Java 代码(可直接提交)
java
import java.util.*;
class Solution {
public int numWays(String[] words, String target) {
final int MOD = 1000000007;
int n = words[0].length(); // 列数
int m = target.length(); // target 长度
char[] t = target.toCharArray();
// 预处理:cnt[j][c] = 第 j 列字符 c 的出现次数
long[][] cnt = new long[n][26];
for (String w : words) {
for (int j = 0; j < n; j++) {
cnt[j][w.charAt(j) - 'a']++;
}
}
// dp[i][j] = 前 j 列,拼 target 前 i 个字符的方案数
long[][] dp = new long[m + 1][n + 1];
// 边界:拼 0 个字符,不管多少列都是 1 种方案
for (int j = 0; j <= n; j++) {
dp[0][j] = 1;
}
for (int i = 1; i <= m; i++) {
char c = t[i - 1];
for (int j = 1; j <= n; j++) {
// 不选第 j 列
dp[i][j] = dp[i][j - 1];
// 选第 j 列
long add = dp[i - 1][j - 1] * cnt[j - 1][c - 'a'];
dp[i][j] = (dp[i][j] + add) % MOD;
}
}
return (int) (dp[m][n] % MOD);
}
}
空间优化版(可选)
把二维 DP 压成一维,从后往前更新避免覆盖:
java
class Solution {
public int numWays(String[] words, String target) {
final int MOD = 1000000007;
int n = words[0].length();
int m = target.length();
char[] t = target.toCharArray();
long[][] cnt = new long[n][26];
for (String w : words) {
for (int j = 0; j < n; j++) {
cnt[j][w.charAt(j) - 'a']++;
}
}
long[] dp = new long[m + 1];
dp[0] = 1;
for (int j = 0; j < n; j++) {
// 从后往前,避免覆盖
for (int i = m; i >= 1; i--) {
char c = t[i - 1];
dp[i] = (dp[i] + dp[i - 1] * cnt[j][c - 'a']) % MOD;
}
}
return (int) dp[m];
}
}
如果你愿意,我可以顺便给你写 C++ / Python / Go / TypeScript 版本,或者把这道题的 DP 转移过程用例子一步步演算给你看,方便彻底理解。
更多推荐




所有评论(0)