当前位置: 首页 > news >正文

千问 LeetCode 2472.不重叠回文子字符串的最大数目 Go实现

好的,这是 LeetCode 2472 "不重叠回文子字符串的最大数目" 的 Go 语言实现。

解题思路

核心是动态规划 + 中心扩展法:

1. 定义 dp[i] 表示 s[0..i-1] 中能选出的最大回文子串数目
2. 对于每个位置 i,有两种选择:
- 不选 s[i-1]:dp[i] = dp[i-1]
- 选以某个位置结尾的回文串:找到所有以 i-1 结尾且长度 ≥ k 的回文串

Go 实现

func maxPalindromes(s string, k int) int {
n := len(s)
dp := make([]int, n+1)

// 中心扩展法
for center := 0; center < 2*n-1; center++ {
left := center / 2
right := left + center%2

// 不选当前字符的情况
if left+1 <= n {
dp[left+1] = max(dp[left+1], dp[left])
}

// 向两边扩展,寻找回文串
for left >= 0 && right < n && s[left] == s[right] {
length := right - left + 1
if length >= k {
// 找到长度 ≥ k 的回文串,更新 dp
dp[right+1] = max(dp[right+1], dp[left]+1)
break // 贪心:找到第一个长度 ≥ k 的就停止
}
left--
right++
}
}

return dp[n]
}

func max(a, b int) int {
if a > b {
return a
}
return b
}

另一种实现(预处理回文串 + DP)

func maxPalindromes(s string, k int) int {
n := len(s)
dp := make([]int, n+1)

// 预处理所有回文串
isPalindrome := make([][]bool, n)
for i := range isPalindrome {
isPalindrome[i] = make([]bool, n)
}

// 从下往上,从左往右填充
for i := n - 1; i >= 0; i-- {
for j := i; j < n; j++ {
if s[i] == s[j] {
if j-i <= 2 {
isPalindrome[i][j] = true
} else {
isPalindrome[i][j] = isPalindrome[i+1][j-1]
}
}
}
}

// DP
for i := 1; i <= n; i++ {
dp[i] = dp[i-1] // 不选 s[i-1]

// 枚举以 i-1 结尾的回文串
for j := i - k; j >= 0; j-- {
if isPalindrome[j][i-1] {
dp[i] = max(dp[i], dp[j]+1)
break // 贪心优化
}
}
}

return dp[n]
}

优化版本(只检查长度 k 和 k+1)

利用性质:只需检查长度为 k 和 k+1 的回文串,因为更长的回文串可以去掉首尾得到更短的。

func maxPalindromes(s string, k int) int {
n := len(s)
dp := make([]int, n+1)

// 预处理回文串
isPalindrome := make([][]bool, n)
for i := range isPalindrome {
isPalindrome[i] = make([]bool, n)
}

for i := n - 1; i >= 0; i-- {
for j := i; j < n; j++ {
if s[i] == s[j] {
if j-i <= 2 {
isPalindrome[i][j] = true
} else {
isPalindrome[i][j] = isPalindrome[i+1][j-1]
}
}
}
}

// DP - 只检查长度 k 和 k+1
for i := 1; i <= n; i++ {
dp[i] = dp[i-1]

// 检查长度为 k 的回文串
if i >= k && isPalindrome[i-k][i-1] {
dp[i] = max(dp[i], dp[i-k]+1)
}

// 检查长度为 k+1 的回文串
if i >= k+1 && isPalindrome[i-k-1][i-1] {
dp[i] = max(dp[i], dp[i-k-1]+1)
}
}

return dp[n]
}

示例验证

示例 1:
s = "abaccdbbd", k = 3
输出:2
解释:选择 "aba" 和 "dbbd"

示例 2:
s = "adbcda", k = 2
输出:0
解释:不存在长度 ≥ 2 的回文串

复杂度分析

- 时间复杂度:O(n²),中心扩展法或预处理回文串
- 空间复杂度:O(n²)(预处理版本)或 O(n)(中心扩展版本)

测试代码

func main() {
// 测试用例
fmt.Println(maxPalindromes("abaccdbbd", 3)) // 输出: 2
fmt.Println(maxPalindromes("adbcda", 2)) // 输出: 0
fmt.Println(maxPalindromes("aaa", 2)) // 输出: 1
fmt.Println(maxPalindromes("abba", 2)) // 输出: 1
}

推荐使用中心扩展法的实现,空间复杂度更优,且不需要额外的预处理数组。一

http://www.cnnetsun.cn/news/2444206.html

相关文章:

  • 避开DSP28337D ePWM的坑:Trip-Zone配置中的5个常见误区与调试心得
  • 手把手教你用GDB/LLDB调试器观察寄存器状态(附实战案例)
  • 如何在Windows平台高效使用WinFlexBison构建解析器:终极实战指南
  • 从纸质到数字:10分钟用Audiveris让乐谱重获新生
  • 智能体测试策略:单元测试、集成测试与模拟LLM
  • 【技术解析】从点测量到全场感知:DIC三维应变测量如何革新传统应变片测试范式
  • VMware Unlocker终极指南:在Windows/Linux上运行macOS虚拟机
  • 别再死磕仿真了!用STA搞定数字芯片时序验证,这篇保姆级入门指南就够了
  • NotebookLM教育研究辅助实战指南:5个被93%高校研究者忽略的高阶用法
  • 量子退火在CPS测试用例生成中的应用与优化
  • 书匠策AI:你的论文降重+降AIGC双buff神器,官网www.shujiangce.com亲测真香!
  • 基于 YOLOv8 的猫狗图像分类项目全流程复盘
  • SpringBoot3实战:Thymeleaf模板引擎的现代化Web开发指南
  • 如何在Gitee和GitHub上建立远程仓库?(手把手教学)
  • 2026下半年数据库趋势:多模、云原生、AI融合
  • 如何快速掌握炉石传说游戏自动化:开源智能助手完整教程
  • QT ToolButton的5个隐藏技巧与3个常见坑,新手避雷指南(基于Qt 6.5)
  • MySQL 跑得稳不稳,Prometheus 得能抓到这个数据才能说清楚
  • CircuitPython HID实战:用Python轻松打造自定义键盘鼠标与数据记录仪
  • 国产多模态大模型崛起:技术、场景与未来挑战全解析
  • 国产多模态大模型:技术自主之路与未来蓝图
  • 如何彻底卸载干净Python(已安装的Python版本)
  • 嵌入式开发实战:从防御性编程到安全启动,构建高可靠系统的核心方法论
  • CoreSight SoC-400交叉触发接口配置详解
  • 支付系统架构设计:从交易核心到资金核算的稳定性实践
  • 项目实训个人博客(五)
  • 自定义Spring Boot Actuator端点
  • 2026年主流会议记录软件大横评,全场景实测对比,差距竟然这么大,黑马意外胜出
  • 【深度解析】Hermes Agent 0.14.0:本地代理、会话交接与自主工作流架构实践
  • 跨平台图形API实战选型:从Vulkan、DirectX到Metal与WebGPU的架构抉择