$bytePos) { $insertions[] = [$bytePos, '步骤'.self::chineseOrdinal($i + 1).':']; } usort($insertions, static fn (array $a, array $b): int => $b[0] <=> $a[0]); $out = $solution; foreach ($insertions as [$pos, $label]) { $out = substr($out, 0, $pos).$label.substr($out, $pos); } return $out; } /** * 严格按 1、2、3… 顺序在字符串中找第一条 (n) 或 (中文 n),且该位置须处于小问边界(段首或句末标点后)。 * * @return list UTF-8 字节偏移 */ private static function collectOrderedSubQuestionByteOffsets(string $s, int $maxN): array { $offsets = []; $searchFrom = 0; for ($n = 1; $n <= $maxN; $n++) { $hit = self::findNextAnchoredSubQuestion($s, $searchFrom, $n); if ($hit === null) { break; } [$byteStart, $matchLen] = $hit; $offsets[] = $byteStart; $searchFrom = $byteStart + $matchLen; } return $offsets; } /** * @return ?array{0: int, 1: int} [byteStart, matchByteLength] */ private static function findNextAnchoredSubQuestion(string $s, int $searchFrom, int $n): ?array { $cn = self::chineseOrdinal($n); // 全角括号 + 阿拉伯数字(1)(2)在解析/OCR 中极常见;原先仅支持(一)(二)会漏检整条小问链 $pattern = '/(? '一', 2 => '二', 3 => '三', 4 => '四', 5 => '五', 6 => '六', 7 => '七', 8 => '八', 9 => '九', 10 => '十', ]; if (isset($map[$n])) { return $map[$n]; } if ($n > 10 && $n <= 19) { return '十'.$map[$n - 10]; } return (string) $n; } }