news 2026/7/4 3:55:30

Kimi LeetCode 3455. 最短匹配子字符串 Go实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Kimi LeetCode 3455. 最短匹配子字符串 Go实现

LeetCode 3455. 最短匹配子字符串 — Go 实现(可直接提交)

核心思路

将 `p` 按 `'*'` 分割为 `left * mid * right` 三部分。用 KMP 分别找出三者在 `s` 中的所有匹配位置,然后用双指针枚举 `mid` 的每个出现位置,寻找最靠右的合法 `left` 和最靠左的合法 `right`,使得子串长度最短。

关键:若某部分为空串,则视为在 `s` 的每个位置(包括末尾)都匹配,返回 `[0, 1, ..., n]`。

---

完整代码

```go
import (
"math"
"strings"
)

func shortestMatchingSubstring(s string, p string) int {
// 1. 按 '*' 分割为三部分
parts := strings.Split(p, "*")
left, mid, right := parts[0], parts[1], parts[2]

// 2. KMP 找出所有匹配位置
posL := kmpAll(s, left)
posM := kmpAll(s, mid)
posR := kmpAll(s, right)

// 3. 双指针找最短匹配
ans := math.MaxInt32
j := 0 // posL 指针
k := 0 // posR 指针

for _, i2 := range posM {
// left 必须在 mid 开始前结束:i1 + len(left) <= i2
// 找满足条件的最后一个 left(越靠右,子串越短)
for j < len(posL) && posL[j]+len(left) <= i2 {
j++
}
if j == 0 {
continue // 无合法 left
}
i1 := posL[j-1]

// right 必须在 mid 结束后开始:i3 >= i2 + len(mid)
// 找满足条件的第一个 right(越靠左,子串越短)
for k < len(posR) && posR[k] < i2+len(mid) {
k++
}
if k == len(posR) {
break // 后续 mid 更大,不可能再有合法 right
}
i3 := posR[k]

// 子串为 s[i1 : i3+len(right)]
length := i3 + len(right) - i1
if length < ans {
ans = length
}
}

if ans == math.MaxInt32 {
return -1
}
return ans
}

// kmpAll 返回 pattern 在 text 中所有匹配的起始位置
// 若 pattern 为空,返回 [0, 1, ..., len(text)](每个位置都匹配)
func kmpAll(text, pattern string) []int {
if len(pattern) == 0 {
res := make([]int, len(text)+1)
for i := range res {
res[i] = i
}
return res
}

// 计算前缀函数 LPS
m := len(pattern)
lps := make([]int, m)
j := 0
for i := 1; i < m; i++ {
for j > 0 && pattern[i] != pattern[j] {
j = lps[j-1]
}
if pattern[i] == pattern[j] {
j++
lps[i] = j
}
}

// KMP 匹配过程
res := make([]int, 0)
j = 0
for i := 0; i < len(text); i++ {
for j > 0 && text[i] != pattern[j] {
j = lps[j-1]
}
if text[i] == pattern[j] {
j++
}
if j == m {
res = append(res, i-m+1)
j = lps[j-1]
}
}
return res
}
```

---

复杂度分析

指标 复杂度 说明
时间 O(\|s\| + \|p\|) KMP 线性扫描 + 双指针单调移动
空间 O(\|s\| + \|p\|) 存储 LPS 数组和匹配位置列表

---

关键边界测试

输入 输出 说明
`s="abaacbaecebce", p="ba*c*ce"` `8` 常规匹配 `"baecebce"`
`s="baccbaadbc", p="cc*baa*adb"` `-1` 无匹配
`s="a", p="**"` `0` 空串匹配(空 left/mid/right)
`s="aa", p="aa**"` `2` `left="aa"`, `mid=right=""`
`s="madlogic", p="*adlogi*"` `6` 匹配 `"adlogi"`

---

为什么这样是对的?

1. KMP 找所有位置:保证我们能枚举所有可能的匹配组合。
2. 双指针单调性:`posL`、`posM`、`posR` 都是升序数组。随着 `mid` 位置右移,`left` 的最优位置只会右移或不变,`right` 的最优位置也只会右移或不变。因此双指针均摊 O(N)。
3. 空串处理:`kmpAll` 对空 pattern 返回 `[0..n]`,完美覆盖 `p = "**"`、`"a**"`、`"**a"` 等边界情况,无需额外特判。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/4 3:55:20

毕设还剩 30 天?这份倒排计划表,照着做或直接找人做都来得及

毕设还剩 30 天&#xff1f;这份倒排计划表&#xff0c;照着做或直接找人做都来得及目标读者&#xff1a;时间紧、想毕业、正在考虑要不要花钱买进度的同学。 这篇既是自救计划&#xff0c;也是你找我做方案时的标准排期参考。一、30 天能不能搞定&#xff1f;能&#xff0c;但…

作者头像 李华
网站建设 2026/7/4 3:53:11

MinIO 和 RustFS 核心差异梳理:协议、架构、性能全方位对比

目录 一、开源协议&#xff1a;商用约束天差地别&#xff0c;直接决定私有化交付可行性 二、开发语言与内存机制&#xff1a;决定长期运行稳定性 三、元数据架构设计&#xff1a;海量文件场景瓶颈完全不同 四、真实业务性能&#xff1a;小文件与事务场景拉开明显差距 五、…

作者头像 李华
网站建设 2026/7/4 3:50:44

小程序制作工具测评:餐宝盈/BBWEYY/比文云/Vev/Beacon(2026年7月更新)含零代码SAAS、AI编程、源码定制交付

“如何用微信开发者工具开发一个预约小程序”是很多开发者、门店服务团队和本地生活项目负责人都会关注的问题。因为从技术实现角度看&#xff0c;预约小程序并不是简单做一个日期选择页和提交按钮&#xff0c;而是要完成前端页面、服务展示、时间段选择、预约下单、支付定金、…

作者头像 李华
网站建设 2026/7/4 3:50:20

嵌入式 | 学习笔记和资料

嵌入式 | 学习笔记&#x1f4da;和资料 时间&#xff1a;2026年7月1日14:44:52 目录 文章目录嵌入式 | 学习笔记&#x1f4da;和资料目录1.参考2.笔记和资料2-1.嵌入式开发笔记2-2.Linux C函数参考手册(PDF版)2-3.Linux程序设计 中文第4版2-4.Linux设备驱动开发详解(宋宝华)2-…

作者头像 李华
网站建设 2026/7/4 3:49:28

万德高科网关管理软件CNC数据采集使用教程——1.3哈斯CNC数采步骤

一、IP与端口配置&#xff08;一&#xff09;设备基础信息确认1.型号与通讯方式确认&#xff1a;哈斯数控面板分为老版本和新版本&#xff0c;老版本仅支持串口通讯&#xff0c;其网口无法用于数据采集&#xff1b;新版本支持网口通讯&#xff0c;为采集首选方式。2.通讯接口确…

作者头像 李华
网站建设 2026/7/4 3:47:38

拓竹打印机bambu-studio

目录 打印机型号&#xff1a; web访问&#xff1a; 启动docker 打印机型号&#xff1a; Bambu Lab P2S slic3r-console.exe --load my_printer_settings.ini -g model.stl --fill-density 30%切片引擎Slic3r: Slic3r: 可以直接通过系统包管理器安装&#xff0c;非常方便。例…

作者头像 李华