字符串交织问题(三个字符串版本)
字数 1605 2025-11-10 00:01:52

字符串交织问题(三个字符串版本)

题目描述

给定三个字符串s1、s2和s3,判断s3是否能由s1和s2的交织组成。交织是指在不改变s1和s2中字符相对顺序的情况下,将它们交错合并成一个字符串。

例如:

  • 输入:s1 = "aab", s2 = "abc", s3 = "aaabcb"
  • 输出:true
  • 解释:s3可以由s1和s2交织形成:取s1的"aa",然后s2的"ab",再s1的"b",最后s2的"c",形成"aaabcb"

解题思路

这个问题是经典的两个字符串交织问题的扩展。我们需要检查s3是否能被分解为三个子序列,分别来自s1、s2,且保持各自的字符顺序。

动态规划状态定义

定义dp[i][j][k]为布尔值,表示s1的前i个字符、s2的前j个字符、s3的前k个字符是否能形成交织。其中:

  • i ∈ [0, len(s1)],j ∈ [0, len(s2)],k ∈ [0, len(s3)]
  • 当k ≠ i + j时,dp[i][j][k]必然为false,因为总字符数不匹配

状态转移方程

对于每个状态dp[i][j][k],考虑最后一个字符可能来自哪个字符串:

  1. 如果i > 0且s1[i-1] == s3[k-1],那么:
    dp[i][j][k] = dp[i][j][k] || dp[i-1][j][k-1]

  2. 如果j > 0且s2[j-1] == s3[k-1],那么:
    dp[i][j][k] = dp[i][j][k] || dp[i][j-1][k-1]

边界条件

dp[0][0][0] = true(三个空字符串可以交织成空字符串)

算法步骤

  1. 获取字符串长度:n1 = len(s1), n2 = len(s2), n3 = len(s3)
  2. 如果n1 + n2 ≠ n3,直接返回false
  3. 创建三维DP数组dp[n1+1][n2+1][n3+1],初始化为false
  4. 设置边界条件:dp[0][0][0] = true
  5. 三重循环遍历:
    • 第一重:i从0到n1
    • 第二重:j从0到n2
    • 第三重:k从0到n3
  6. 如果k ≠ i + j,跳过(字符数不匹配)
  7. 检查s1的匹配:如果i > 0且s1[i-1] == s3[k-1],更新dp[i][j][k]
  8. 检查s2的匹配:如果j > 0且s2[j-1] == s3[k-1],更新dp[i][j][k]
  9. 最终返回dp[n1][n2][n3]

时间复杂度优化

由于k = i + j,我们可以将三维DP优化为二维:

  • 定义dp[i][j]表示s1的前i个字符和s2的前j个字符能否交织成s3的前i+j个字符
  • 状态转移:
    dp[i][j] = (i > 0 && s1[i-1] == s3[i+j-1] && dp[i-1][j])
    || (j > 0 && s2[j-1] == s3[i+j-1] && dp[i][j-1])

示例验证

以s1 = "aab", s2 = "abc", s3 = "aaabcb"为例:

dp[0][0] = true
dp[1][0] = true (s1[0] == s3[0])
dp[2][0] = true (s1[1] == s3[1])
dp[2][1] = true (s2[0] == s3[2])
dp[2][2] = true (s2[1] == s3[3])
dp[3][2] = true (s1[2] == s3[4])
dp[3][3] = true (s2[2] == s3[5])

最终dp[3][3] = true,验证成功。

字符串交织问题(三个字符串版本) 题目描述 给定三个字符串s1、s2和s3,判断s3是否能由s1和s2的交织组成。交织是指在不改变s1和s2中字符相对顺序的情况下,将它们交错合并成一个字符串。 例如: 输入:s1 = "aab", s2 = "abc", s3 = "aaabcb" 输出:true 解释:s3可以由s1和s2交织形成:取s1的"aa",然后s2的"ab",再s1的"b",最后s2的"c",形成"aaabcb" 解题思路 这个问题是经典的两个字符串交织问题的扩展。我们需要检查s3是否能被分解为三个子序列,分别来自s1、s2,且保持各自的字符顺序。 动态规划状态定义 定义dp[ i][ j][ k ]为布尔值,表示s1的前i个字符、s2的前j个字符、s3的前k个字符是否能形成交织。其中: i ∈ [ 0, len(s1)],j ∈ [ 0, len(s2)],k ∈ [ 0, len(s3) ] 当k ≠ i + j时,dp[ i][ j][ k ]必然为false,因为总字符数不匹配 状态转移方程 对于每个状态dp[ i][ j][ k ],考虑最后一个字符可能来自哪个字符串: 如果i > 0且s1[ i-1] == s3[ k-1 ],那么: dp[ i][ j][ k] = dp[ i][ j][ k] || dp[ i-1][ j][ k-1 ] 如果j > 0且s2[ j-1] == s3[ k-1 ],那么: dp[ i][ j][ k] = dp[ i][ j][ k] || dp[ i][ j-1][ k-1 ] 边界条件 dp[ 0][ 0][ 0 ] = true(三个空字符串可以交织成空字符串) 算法步骤 获取字符串长度:n1 = len(s1), n2 = len(s2), n3 = len(s3) 如果n1 + n2 ≠ n3,直接返回false 创建三维DP数组dp[ n1+1][ n2+1][ n3+1 ],初始化为false 设置边界条件:dp[ 0][ 0][ 0 ] = true 三重循环遍历: 第一重:i从0到n1 第二重:j从0到n2 第三重:k从0到n3 如果k ≠ i + j,跳过(字符数不匹配) 检查s1的匹配:如果i > 0且s1[ i-1] == s3[ k-1],更新dp[ i][ j][ k ] 检查s2的匹配:如果j > 0且s2[ j-1] == s3[ k-1],更新dp[ i][ j][ k ] 最终返回dp[ n1][ n2][ n3 ] 时间复杂度优化 由于k = i + j,我们可以将三维DP优化为二维: 定义dp[ i][ j ]表示s1的前i个字符和s2的前j个字符能否交织成s3的前i+j个字符 状态转移: dp[ i][ j] = (i > 0 && s1[ i-1] == s3[ i+j-1] && dp[ i-1][ j ]) || (j > 0 && s2[ j-1] == s3[ i+j-1] && dp[ i][ j-1 ]) 示例验证 以s1 = "aab", s2 = "abc", s3 = "aaabcb"为例: dp[ 0][ 0 ] = true dp[ 1][ 0] = true (s1[ 0] == s3[ 0 ]) dp[ 2][ 0] = true (s1[ 1] == s3[ 1 ]) dp[ 2][ 1] = true (s2[ 0] == s3[ 2 ]) dp[ 2][ 2] = true (s2[ 1] == s3[ 3 ]) dp[ 3][ 2] = true (s1[ 2] == s3[ 4 ]) dp[ 3][ 3] = true (s2[ 2] == s3[ 5 ]) 最终dp[ 3][ 3 ] = true,验证成功。