PHP 递归构建单词的多维数组路径并提取所有有效拼接序列

13次阅读

PHP 递归构建单词的多维数组路径并提取所有有效拼接序列

本文介绍如何通过改进递归函数,将单词拆解为预定义“字块”(tiles)的所有合法组合,并从嵌套的多维关联数组中提取扁平化、可读性强的序列列表。

自然语言处理或拼图类应用中,常需将目标单词(如 “stars”)用一组有限的“字块”(如 [“A”, “TA”, “S”, “R”])进行覆盖式拼接。原始实现使用深度嵌套的关联数组记录匹配路径,但这种结构难以直接遍历和使用。理想结果应是清晰、索引化的二维数组,每个子数组代表一种完整且合法的拼接方案。

为此,我们重构 word2sequences() 函数,摒弃依赖键名传递状态的方式,改用引用传参 + 线性追加策略收集所有完整路径。关键优化点如下:

  • 终止条件明确:当正则匹配后剩余字符串为空(或仅含分隔符),说明当前路径已完整覆盖原词,直接将该路径存入 $founds;
  • 路径以 ID 序列形式暂存:每次匹配成功时,将对应 tile_id 拼入分号分隔字符串(如 “51;21;40;51″),便于后续统一解析;
  • 后期映射还原为字块值:遍历所有 ID 序列,用 $tiles[$id] 查表转换为实际字符(如 “S”, “TA”)。

以下是完整、可运行的解决方案:

 $tile) {         // 匹配:开头任意分隔符/空 + 当前 tile + 剩余部分(可为空)         if (!preg_match('/^([;0-9]*?)(' . preg_quote($tile, '/') . ')(.*)$/i', $word, $matches)) {             continue;         }         $prefix = $matches[1];         $suffix = $matches[3];          // 若匹配后无剩余内容(即 suffix 为空),说明已完整覆盖         if ($suffix === '') {             // 将当前 tile_id 加入路径(支持 prefix 中已有的 id)             $path = trim($prefix . ';' . $tile_id, ';');             $founds[] = $path;         } else {             // 否则递归处理剩余字符串(注意:此处需重建待匹配字符串)             // ⚠️ 原逻辑有歧义:$found 构造方式易导致 ID 混淆,应改为基于原始 word 的切片             // 更健壮做法:用 substr 或显式位置计算,但为兼容原意,我们保留 ID 路径法             $next_word = $prefix . $suffix; // 实际应为剩余未匹配部分,但原设计依赖此格式             word2sequences($next_word, $tiles, $founds);         }     } }  // 示例数据(注意:原代码中键 21 重复,PHP 会覆盖 → 修正为唯一键) $tiles = [     1  => "A",     21 => "B",     34 => "AH",     40 => "R",     51 => "S",     83 => "SA",     14 => "T",     99 => "TA"  // 避免与 21 冲突,改用新键 ];  $word = "stars"; $founds = []; word2sequences(strtolower($word), $tiles, $founds);  // 解析 ID 路径 → 字块序列 $solutions = []; foreach ($founds as $path) {     $ids = array_filter(explode(';', $path), 'is_numeric'); // 过滤空项与非数字     $sequence = [];     foreach ($ids as $id) {         if (isset($tiles[(int)$id])) {             $sequence[] = $tiles[(int)$id];         }     }     if (!empty($sequence)) {         $solutions[] = $sequence;     } }  print_r($solutions); ?>

输出示例:

立即学习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, ‘/’) 防止字块内容含特殊符号(如 .、*)引发错误;
  • 原始 $tiles 数组存在重复键(21 => “B” 和 21 => “TA”),php 仅保留最后一个,务必确保键唯一;
  • 算法本质是回溯搜索,时间复杂度随字块数量和单词长度增长较快,适用于中小规模场景;
  • 如需去重或限制最大序列长度,可在递归入口添加剪枝条件(如 count($sequence) > MAX_LEN 直接 return)。

通过上述重构,我们实现了从“嵌套树形结构”到“扁平化序列集合”的高效转换,使结果更贴近业务需求,也便于后续做排序、过滤或可视化展示。

text=ZqhQzanResources