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

Kimi K2.6 快速 LeetCode 3213. 最小代价构造字符串 Go实现

LeetCode 3213. 最小代价构造字符串(Construct String with Minimum Cost)的 Go 实现,核心思路是字符串哈希 + 动态规划,这是该题最经典且高效的解法。

---

解题思路

核心思想:字符串哈希 + DP

1. 预处理 `target` 的前缀哈希:使用滚动哈希,在 O(n) 时间内构建前缀哈希数组 `h` 和幂次数组 `p`,从而可以在 O(1) 时间内查询任意子串的哈希值。
2. 预处理 `words` 的哈希值:计算每个 `words[i]` 的哈希值,存入 `map`。相同字符串只保留最小花费。
3. 动态规划:设 `f[i]` 为构造 `target` 前 `i` 个字符的最小花费。
- 状态转移:枚举 `words` 中出现过的所有长度 `len`,若 `target[i-len, i-1]` 的哈希值匹配某个 `word`,则 `f[i] = min(f[i], f[i-len] + cost)`。
4. 优化:只枚举 `words` 中出现过的长度集合,避免无效枚举。

时间复杂度:O(n \times \sqrt{L}),其中 n 为 `target` 长度,L 为所有 `words` 长度之和。

空间复杂度:O(n)。

---

Go 代码实现

```go
package main

import (
"math"
"sort"
)

// Hashing 滚动哈希结构体
type Hashing struct {
p []int64 // 前缀幂次
h []int64 // 前缀哈希
mod int64 // 模数
}

// NewHashing 创建新的哈希对象
func NewHashing(word string, base, mod int64) *Hashing {
n := len(word)
p := make([]int64, n+1)
h := make([]int64, n+1)
p[0] = 1
for i := 1; i <= n; i++ {
p[i] = p[i-1] * base % mod
h[i] = (h[i-1]*base + int64(word[i-1])) % mod
}
return &Hashing{p, h, mod}
}

// query 查询子串 [l, r] 的哈希值(1-based,闭区间)
func (hs *Hashing) query(l, r int) int64 {
return (hs.h[r] - hs.h[l-1]*hs.p[r-l+1]%hs.mod + hs.mod) % hs.mod
}

func minimumCost(target string, words []string, costs []int) int {
const base = 13331
const mod = 998244353
const inf = math.MaxInt32 / 2

n := len(target)
hashing := NewHashing(target, base, mod)

// f[i] 表示构造 target 前 i 个字符的最小花费
f := make([]int, n+1)
for i := range f {
f[i] = inf
}
f[0] = 0

// 收集 words 中所有出现过的长度(去重)
ss := make(map[int]struct{})
for _, w := range words {
ss[len(w)] = struct{}{}
}
lengths := make([]int, 0, len(ss))
for length := range ss {
lengths = append(lengths, length)
}
sort.Ints(lengths)

// 计算每个 word 的哈希值,相同字符串保留最小花费
d := make(map[int64]int)
for i, w := range words {
var x int64
for _, c := range w {
x = (x*base + int64(c)) % mod
}
if existingCost, exists := d[x]; exists {
if costs[i] < existingCost {
d[x] = costs[i]
}
} else {
d[x] = costs[i]
}
}

// 动态规划
for i := 1; i <= n; i++ {
for _, j := range lengths {
if j > i {
break
}
x := hashing.query(i-j+1, i)
if cost, ok := d[x]; ok {
f[i] = min(f[i], f[i-j]+cost)
}
}
}

if f[n] >= inf {
return -1
}
return f[n]
}
```

---

关键点说明

要点 说明
哈希冲突 使用单哈希(模数 `998244353`,基数 `13331`)在 LeetCode 上通常可通过。若担心冲突,可改用双哈希。
相同字符串处理 `d` map 中相同哈希值只保留最小花费,避免重复计算。
长度枚举优化 用 `map` 去重 + `sort` 排序,只枚举实际出现过的长度,大幅减少无效循环。
1-based 索引 `query(l, r)` 使用 1-based 闭区间,与 DP 数组 `f[i]`(前 `i` 个字符)对应。

---

示例验证

输入:`target = "abcdef"`, `words = ["abdef","abc","d","def","ef"]`, `costs = [100,1,1,10,5]`

- `f[3] = f[0] + cost("abc") = 0 + 1 = 1`
- `f[4] = f[3] + cost("d") = 1 + 1 = 2`
- `f[6] = f[4] + cost("ef") = 2 + 5 = 7`

输出:`7` ✓

---

另一种解法:后缀数组(Go 标准库)

Go 标准库 `index/suffixarray` 提供了后缀数组实现,可以直接使用,代码更简洁:

```go
import (
"index/suffixarray"
"math"
)

func minimumCost(target string, words []string, costs []int) int {
minCost := map[string]uint16{}
for i, w := range words {
c := uint16(costs[i])
if minCost[w] == 0 {
minCost[w] = c
} else {
minCost[w] = min(minCost[w], c)
}
}

n := len(target)
type pair struct{ l, cost uint16 }
from := make([][]pair, n+1)
sa := suffixarray.New([]byte(target))
for w, c := range minCost {
for _, l := range sa.Lookup([]byte(w), -1) {
r := l + len(w)
from[r] = append(from[r], pair{uint16(l), c})
}
}

f := make([]int, n+1)
for i := 1; i <= n; i++ {
f[i] = math.MaxInt / 2
for _, p := range from[i] {
f[i] = min(f[i], f[p.l]+int(p.cost))
}
}
if f[n] == math.MaxInt/2 {
return -1
}
return f[n]
}
```

两种方法均可通过,哈希法更通用,后缀数组法在 Go 中代码更简洁。

http://www.jsqmd.com/news/1010882/

相关文章:

  • 猫抓Cat-Catch终极指南:3分钟成为浏览器资源嗅探专家
  • 如何快速掌握Typora自动编号功能:面向新手的完整实战指南
  • 内容发了没人看_AI智能发布时机可能是你忽略的那块短板
  • 2026阜阳市民高频光顾的 5 家线下黄金回收白银铂金回收实体店实地走访测评 - 中安检金银铂钻回收
  • 本地部署Llama-3.1替代Claude API的实战指南
  • 2026广西本地贵金属变现门店精选前五+黄金铂金白银金条回收合规商家名录 含地址电话 - 诚金汇钻回收公司
  • 2026成都市民高频光顾的 5 家线下黄金回收白银铂金回收实体店实地走访测评 - 中安检金银铂钻回收
  • 2026保山市民高频光顾的 5 家线下黄金回收白银铂金回收实体店实地走访测评 - 中安检金银铂钻回收
  • C++并发编程选型指南:何时该用无锁队列concurrentqueue,何时用STL queue就够了?
  • 2026鄂尔多斯市民高频光顾的 5 家线下黄金回收白银铂金回收实体店实地走访测评 - 中安检金银铂钻回收
  • 手动发五六个平台太累了_AI全渠道发布是不是解法
  • 避坑必看!2026上海奢侈品黄金回收TOP6实测:机构套路大起底,零套路诚信标杆出炉 - 奢侈品回收
  • 河南郑州GEO服务商如何选择更合适?
  • 2026大连市民高频光顾的 5 家线下黄金回收白银铂金回收实体店实地走访测评 - 中安检金银铂钻回收
  • 2026鄂尔多斯本地贵金属变现门店精选前五+黄金铂金白银金条回收合规商家名录 含地址电话 - 诚金汇钻回收公司
  • 倪妮、章若楠等多元花旦角逐新时代最受欢迎女演员奖项
  • 2026河源本地贵金属变现门店精选前五+黄金铂金白银金条回收合规商家名录 含地址电话 - 诚金汇钻回收公司
  • 2026海南本地贵金属变现门店精选前五+黄金铂金白银金条回收合规商家名录 含地址电话 - 诚金汇钻回收公司
  • 2026滁州本地贵金属变现门店精选前五+黄金铂金白银金条回收合规商家名录 含地址电话 - 诚金汇钻回收公司
  • esp32开发与应用(esp32的tf卡读写)
  • 沈阳新民市水管漏水检测精准查找,测漏水专业治理,全屋漏水检测精准定位 - 同城资讯
  • 2026广州黄金奢侈品回收行业渠道测评:耀辉11大区全域覆盖领跑华南 - 奢侈品回收
  • 2026鄂州市民高频光顾的 5 家线下黄金回收白银铂金回收实体店实地走访测评 - 中安检金银铂钻回收
  • 拯救者工具箱启动崩溃:从故障诊断到深度修复的完整指南
  • MySQL高可用方案选型:MHA vs. Orchestrator vs. 云RDS,我们为什么最终选择了MHA?
  • 2026迪庆本地贵金属变现门店精选前五+黄金铂金白银金条回收合规商家名录 含地址电话 - 诚金汇钻回收公司
  • 2026滨州市民高频光顾的 5 家线下黄金回收白银铂金回收实体店实地走访测评 - 中安检金银铂钻回收
  • 2026广元本地贵金属变现门店精选前五+黄金铂金白银金条回收合规商家名录 含地址电话 - 诚金汇钻回收公司
  • 2026 北京奢侈品黄金回收品牌实力排名,耀辉稳居第一 - 奢侈品回收
  • 碧蓝航线Alas自动化脚本:7x24小时全自动游戏管理终极指南