
本文介绍如何通过递归遍历多维数组结构,将嵌套的瓷砖匹配结果扁平化为清晰的二维数组序列,从而还原出所有可能的单词拼接方案。
在单词拼图类应用中(如 Scrabble 风格的瓷砖组合),常需将目标单词(如 "stars")拆解为若干预定义“瓷砖”(tiles)的有序组合,例如 ["S", "TA", "R", "S"] 或 ["S", "T", "A", "R", "S"]。原始实现中,word2sequences() 函数通过正则匹配与递归生成了一个深度嵌套的关联数组,虽能反映匹配路径,但难以直接用于后续逻辑(如去重、排序、渲染或计分)。因此,关键挑战在于:如何将该嵌套结构完整、无遗漏地展开为扁平化的二维序列数组?
核心思路是重构递归函数,放弃以 tile 值为键的嵌套映射,转而使用线性累加的索引数组存储每条完整路径。优化后的 word2sequences() 不再返回嵌套结构,而是通过引用参数 $founds 直接追加每条终止路径(即完全匹配完毕的序列 ID 列表),并在回溯完成后统一映射为实际 tile 字符串。
以下是完整可运行的解决方案:
"A", "21"=>"TA"])
* @param array &$founds 引用参数,用于累积所有找到的 tile_id 序列(字符串,以分号分隔)
*/
function word2sequences($word, $tiles, &$founds = []) {
// 遍历所有可用瓷砖
foreach ($tiles as $tile_id => $tile) {
// 正则匹配:尝试从单词开头匹配当前 tile(支持前缀数字/分号,用于内部递归标记)
if (!preg_match('/^([;0-9]*?)(' . preg_quote($tile, '/') . ')(.*)$/i', $word, $matches)) {
continue;
}
// 构造新状态:前缀 + 当前 tile_id + 后缀
$remaining = $matches[1] . ';' . $tile_id . ';' . $matches[3];
// 若剩余部分为空(即完全匹配),则记录当前路径
if ($matches[3] === '') {
$founds[] = trim($remaining, ';');
} else {
// 否则继续递归处理剩余部分
word2sequences($matches[3], $tiles, $founds);
}
}
}
// 示例数据:注意键必须唯一,原示例中 21 重复,已修正
$tiles = [
1 => "A",
21 => "B", // 保留原键,但避免冲突;若需 "TA",应使用不同键
34 => "AH",
40 => "R",
51 => "S",
83 => "SA",
14 => "T",
99 => "TA", // 修改为唯一键 99,避免覆盖 21
];
$word = "stars";
$founds = []; // 存储所有 tile_id 序列(字符串)
word2sequences(strtolower($word), $tiles, $founds);
// 将 tile_id 序列转换为实际 tile 字符串序列
$result = [];
foreach ($founds as $idSequence) {
$ids = array_filter(explode(';', $idSequence), 'is_numeric'); // 安全分割并过滤空项
$sequence = [];
foreach ($ids as $id) {
if (isset($tiles[$id])) {
$sequence[] = $tiles[$id];
}
}
if (!empty($sequence)) {
$result[] = $sequence;
}
}
print_r($result);
?>输出示例:
立即学习“PHP免费学习笔记(深入)”;
Array
(
[0] => Array
(
[0] => S
[1] => TA
[2] => R
[3] => S
)
[1] => Array
(
[0] => S
[1] => T
[2] => A
[3] => R
[4] => S
)
)✅ 关键改进点说明:
- 正则安全加固:使用 preg_quote($tile, '/') 防止 tile 内含特殊字符导致正则错误;
- 键唯一性保障:PHP 数组键不可重复,原示例中 21 => "B" 和 21 => "TA" 会覆盖,务必确保 $tiles 键唯一;
- 路径终止判断更鲁棒:仅当 $matches[3] === ''(后缀为空)才视为完整匹配,避免误判;
- ID 提取健壮性:array_filter(..., 'is_numeric') 过滤掉可能混入的空段或非数字标识;
- 大小写兼容:对输入 $word 统一转小写,配合正则 /i 标志,提升匹配容错率。
? 进阶建议:
- 如需去重相同序列,可在最后对 $result 进行 array_unique($result, SORT_REGULAR);
- 若需按长度或字典序排序,可用 usort($result, fn($a, $b) => count($a) count($b) ?: strcmp(implode('', $a), implode('', $b)));;
- 对于长单词或大量 tiles,建议加入递归深度限制或改用迭代 DFS/BFS 避免栈溢出。











