如何修复Python字符串片段拼接匹配函数的逻辑缺陷?
问题分析
你的原代码采用的是贪心式的逐字符匹配策略:从左到右逐个字符拼接临时字符串,一旦匹配到片段列表中的项就重置临时字符串。这种思路的致命缺陷是——它只会选择最早遇到的匹配片段,而不会考虑后续是否有更长的、能让整个字符串完成拼接的匹配项。
比如在第二个测试用例中,匹配完dis后,原代码会优先匹配il,但剩下的子串lusioned无法被列表中的任何片段覆盖,导致最终返回False;但实际上我们需要跳过il,选择匹配更长的illusio,才能完成整个字符串的拼接。
解决方案:尝试所有可能的匹配路径
要解决这个问题,我们需要让算法尝试所有可能的匹配方式,而不是只走贪心的单一路径。下面提供两种常用的实现思路:
方法1:递归回溯 + 记忆化优化
核心思路是从字符串的起始位置开始,尝试用列表中的每一个片段去匹配当前位置的子串,如果匹配成功,就递归检查剩下的子串能否被拼接。只要有一条路径能走到字符串末尾,就返回True。
为了避免重复计算相同位置的子问题,我们可以用记忆化缓存来优化性能:
from functools import lru_cache def canCreateString(pieces, wholeString): @lru_cache(maxsize=None) def backtrack(start_idx): # 已经走到字符串末尾,说明拼接成功 if start_idx == len(wholeString): return True # 遍历所有片段,尝试匹配当前起始位置的子串 for piece in pieces: piece_length = len(piece) # 检查当前起始位置开始的子串是否和片段匹配 if wholeString.startswith(piece, start_idx): # 递归检查剩余部分,如果剩余部分能拼接成功,直接返回True if backtrack(start_idx + piece_length): return True # 所有片段都尝试过,无法匹配当前位置及后续子串 return False return backtrack(0)
方法2:动态规划
我们可以用动态规划数组dp来记录状态:dp[i]表示目标字符串的前i个字符能否被片段列表拼接出来。
def canCreateString(pieces, wholeString): str_length = len(wholeString) # dp数组,dp[0]表示空字符串可以被拼接(基础情况) dp = [False] * (str_length + 1) dp[0] = True for i in range(str_length + 1): # 如果前i个字符能被拼接,就尝试用所有片段去匹配后续子串 if dp[i]: for piece in pieces: piece_len = len(piece) # 检查当前位置i之后的子串是否能匹配该片段 if i + piece_len <= str_length and wholeString[i:i+piece_len] == piece: dp[i + piece_len] = True # 返回整个字符串能否被拼接的结果 return dp[str_length]
测试验证
用你的两个测试用例验证:
# 测试用例1 print(canCreateString(["dis", "il", "lusio", "ned"], "disillusioned")) # 输出True # 测试用例2 print(canCreateString(["dis", "il", "illusio", "ned"], "disillusioned")) # 输出True
两种方法都能正确返回预期结果,解决了原代码的逻辑缺陷。
内容的提问来源于stack exchange,提问作者Ochmar
相关产品推荐
相关产品推荐

