Skip to content

Commit 2897af4

Browse files
authored
feat: add solutions for lc No.3213 (#5172)
1 parent 3bfc96a commit 2897af4

4 files changed

Lines changed: 410 additions & 0 deletions

File tree

solution/3200-3299/3213.Construct String with Minimum Cost/README.md

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,146 @@ func minimumCost(target string, words []string, costs []int) int {
348348
}
349349
```
350350

351+
#### TypeScript
352+
353+
```ts
354+
class Hashing {
355+
private p: bigint[];
356+
private h: bigint[];
357+
private mod: bigint;
358+
359+
constructor(word: string, base: number, mod: number) {
360+
const n = word.length;
361+
this.mod = BigInt(mod);
362+
const b = BigInt(base);
363+
this.p = new Array(n + 1);
364+
this.h = new Array(n + 1);
365+
this.p[0] = 1n;
366+
this.h[0] = 0n;
367+
for (let i = 1; i <= n; i++) {
368+
this.p[i] = (this.p[i - 1] * b) % this.mod;
369+
this.h[i] = (this.h[i - 1] * b + BigInt(word.charCodeAt(i - 1))) % this.mod;
370+
}
371+
}
372+
373+
public query(l: number, r: number): number {
374+
const res = (this.h[r] - this.h[l - 1] * this.p[r - l + 1] % this.mod + this.mod) % this.mod;
375+
return Number(res);
376+
}
377+
}
378+
379+
function minimumCost(target: string, words: string[], costs: number[]): number {
380+
const base = 13331;
381+
const mod = 998244353;
382+
const inf = 1e9;
383+
const n = target.length;
384+
const hashing = new Hashing(target, base, mod);
385+
const f = new Array(n + 1).fill(inf);
386+
f[0] = 0;
387+
388+
const ss = Array.from(new Set(words.map(w => w.length))).sort((a, b) => a - b);
389+
const d = new Map<number, number>();
390+
391+
for (let i = 0; i < words.length; i++) {
392+
let x = 0n;
393+
const b = BigInt(base);
394+
const m = BigInt(mod);
395+
const word = words[i];
396+
for (let j = 0; j < word.length; j++) {
397+
x = (x * b + BigInt(word.charCodeAt(j))) % m;
398+
}
399+
const hashVal = Number(x);
400+
d.set(hashVal, Math.min(d.get(hashVal) ?? inf, costs[i]));
401+
}
402+
403+
for (let i = 1; i <= n; i++) {
404+
for (const j of ss) {
405+
if (j > i) break;
406+
const x = hashing.query(i - j + 1, i);
407+
if (d.has(x)) {
408+
f[i] = Math.min(f[i], f[i - j] + d.get(x)!);
409+
}
410+
}
411+
}
412+
413+
return f[n] >= inf ? -1 : f[n];
414+
}
415+
```
416+
417+
#### Rust
418+
419+
```rust
420+
use std::collections::{HashMap, BTreeSet};
421+
use std::cmp::min;
422+
423+
struct Hashing {
424+
p: Vec<i64>,
425+
h: Vec<i64>,
426+
mod_val: i64,
427+
}
428+
429+
impl Hashing {
430+
fn new(word: &str, base: i64, mod_val: i64) -> Self {
431+
let n = word.len();
432+
let mut p = vec![0; n + 1];
433+
let mut h = vec![0; n + 1];
434+
p[0] = 1;
435+
let chars: Vec<u8> = word.bytes().collect();
436+
for i in 1..=n {
437+
p[i] = p[i - 1] * base % mod_val;
438+
h[i] = (h[i - 1] * base + chars[i - 1] as i64) % mod_val;
439+
}
440+
Hashing { p, h, mod_val }
441+
}
442+
443+
fn query(&self, l: usize, r: usize) -> i64 {
444+
(self.h[r] - self.h[l - 1] * self.p[r - l + 1] % self.mod_val + self.mod_val) % self.mod_val
445+
}
446+
}
447+
448+
impl Solution {
449+
pub fn minimum_cost(target: String, words: Vec<String>, costs: Vec<i32>) -> i32 {
450+
let base = 13331i64;
451+
let mod_val = 998244353i64;
452+
let inf = i32::MAX / 2;
453+
let n = target.len();
454+
let hashing = Hashing::new(&target, base, mod_val);
455+
456+
let mut f = vec![inf; n + 1];
457+
f[0] = 0;
458+
459+
let mut ss = BTreeSet::new();
460+
for w in &words {
461+
ss.insert(w.len());
462+
}
463+
464+
let mut d = HashMap::new();
465+
for i in 0..words.len() {
466+
let mut x = 0i64;
467+
for c in words[i].bytes() {
468+
x = (x * base + c as i64) % mod_val;
469+
}
470+
let entry = d.entry(x).or_insert(inf);
471+
*entry = min(*entry, costs[i]);
472+
}
473+
474+
for i in 1..=n {
475+
for &j in &ss {
476+
if j > i {
477+
break;
478+
}
479+
let x = hashing.query(i - j + 1, i);
480+
if let Some(&cost) = d.get(&x) {
481+
f[i] = min(f[i], f[i - j] + cost);
482+
}
483+
}
484+
}
485+
486+
if f[n] >= inf { -1 } else { f[n] }
487+
}
488+
}
489+
```
490+
351491
<!-- tabs:end -->
352492

353493
<!-- solution:end -->

solution/3200-3299/3213.Construct String with Minimum Cost/README_EN.md

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,146 @@ func minimumCost(target string, words []string, costs []int) int {
348348
}
349349
```
350350

351+
#### TypeScript
352+
353+
```ts
354+
class Hashing {
355+
private p: bigint[];
356+
private h: bigint[];
357+
private mod: bigint;
358+
359+
constructor(word: string, base: number, mod: number) {
360+
const n = word.length;
361+
this.mod = BigInt(mod);
362+
const b = BigInt(base);
363+
this.p = new Array(n + 1);
364+
this.h = new Array(n + 1);
365+
this.p[0] = 1n;
366+
this.h[0] = 0n;
367+
for (let i = 1; i <= n; i++) {
368+
this.p[i] = (this.p[i - 1] * b) % this.mod;
369+
this.h[i] = (this.h[i - 1] * b + BigInt(word.charCodeAt(i - 1))) % this.mod;
370+
}
371+
}
372+
373+
public query(l: number, r: number): number {
374+
const res = (this.h[r] - this.h[l - 1] * this.p[r - l + 1] % this.mod + this.mod) % this.mod;
375+
return Number(res);
376+
}
377+
}
378+
379+
function minimumCost(target: string, words: string[], costs: number[]): number {
380+
const base = 13331;
381+
const mod = 998244353;
382+
const inf = 1e9;
383+
const n = target.length;
384+
const hashing = new Hashing(target, base, mod);
385+
const f = new Array(n + 1).fill(inf);
386+
f[0] = 0;
387+
388+
const ss = Array.from(new Set(words.map(w => w.length))).sort((a, b) => a - b);
389+
const d = new Map<number, number>();
390+
391+
for (let i = 0; i < words.length; i++) {
392+
let x = 0n;
393+
const b = BigInt(base);
394+
const m = BigInt(mod);
395+
const word = words[i];
396+
for (let j = 0; j < word.length; j++) {
397+
x = (x * b + BigInt(word.charCodeAt(j))) % m;
398+
}
399+
const hashVal = Number(x);
400+
d.set(hashVal, Math.min(d.get(hashVal) ?? inf, costs[i]));
401+
}
402+
403+
for (let i = 1; i <= n; i++) {
404+
for (const j of ss) {
405+
if (j > i) break;
406+
const x = hashing.query(i - j + 1, i);
407+
if (d.has(x)) {
408+
f[i] = Math.min(f[i], f[i - j] + d.get(x)!);
409+
}
410+
}
411+
}
412+
413+
return f[n] >= inf ? -1 : f[n];
414+
}
415+
```
416+
417+
#### Rust
418+
419+
```rust
420+
use std::collections::{HashMap, BTreeSet};
421+
use std::cmp::min;
422+
423+
struct Hashing {
424+
p: Vec<i64>,
425+
h: Vec<i64>,
426+
mod_val: i64,
427+
}
428+
429+
impl Hashing {
430+
fn new(word: &str, base: i64, mod_val: i64) -> Self {
431+
let n = word.len();
432+
let mut p = vec![0; n + 1];
433+
let mut h = vec![0; n + 1];
434+
p[0] = 1;
435+
let chars: Vec<u8> = word.bytes().collect();
436+
for i in 1..=n {
437+
p[i] = p[i - 1] * base % mod_val;
438+
h[i] = (h[i - 1] * base + chars[i - 1] as i64) % mod_val;
439+
}
440+
Hashing { p, h, mod_val }
441+
}
442+
443+
fn query(&self, l: usize, r: usize) -> i64 {
444+
(self.h[r] - self.h[l - 1] * self.p[r - l + 1] % self.mod_val + self.mod_val) % self.mod_val
445+
}
446+
}
447+
448+
impl Solution {
449+
pub fn minimum_cost(target: String, words: Vec<String>, costs: Vec<i32>) -> i32 {
450+
let base = 13331i64;
451+
let mod_val = 998244353i64;
452+
let inf = i32::MAX / 2;
453+
let n = target.len();
454+
let hashing = Hashing::new(&target, base, mod_val);
455+
456+
let mut f = vec![inf; n + 1];
457+
f[0] = 0;
458+
459+
let mut ss = BTreeSet::new();
460+
for w in &words {
461+
ss.insert(w.len());
462+
}
463+
464+
let mut d = HashMap::new();
465+
for i in 0..words.len() {
466+
let mut x = 0i64;
467+
for c in words[i].bytes() {
468+
x = (x * base + c as i64) % mod_val;
469+
}
470+
let entry = d.entry(x).or_insert(inf);
471+
*entry = min(*entry, costs[i]);
472+
}
473+
474+
for i in 1..=n {
475+
for &j in &ss {
476+
if j > i {
477+
break;
478+
}
479+
let x = hashing.query(i - j + 1, i);
480+
if let Some(&cost) = d.get(&x) {
481+
f[i] = min(f[i], f[i - j] + cost);
482+
}
483+
}
484+
}
485+
486+
if f[n] >= inf { -1 } else { f[n] }
487+
}
488+
}
489+
```
490+
351491
<!-- tabs:end -->
352492

353493
<!-- solution:end -->
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
use std::collections::{HashMap, BTreeSet};
2+
use std::cmp::min;
3+
4+
struct Hashing {
5+
p: Vec<i64>,
6+
h: Vec<i64>,
7+
mod_val: i64,
8+
}
9+
10+
impl Hashing {
11+
fn new(word: &str, base: i64, mod_val: i64) -> Self {
12+
let n = word.len();
13+
let mut p = vec![0; n + 1];
14+
let mut h = vec![0; n + 1];
15+
p[0] = 1;
16+
let chars: Vec<u8> = word.bytes().collect();
17+
for i in 1..=n {
18+
p[i] = p[i - 1] * base % mod_val;
19+
h[i] = (h[i - 1] * base + chars[i - 1] as i64) % mod_val;
20+
}
21+
Hashing { p, h, mod_val }
22+
}
23+
24+
fn query(&self, l: usize, r: usize) -> i64 {
25+
(self.h[r] - self.h[l - 1] * self.p[r - l + 1] % self.mod_val + self.mod_val) % self.mod_val
26+
}
27+
}
28+
29+
impl Solution {
30+
pub fn minimum_cost(target: String, words: Vec<String>, costs: Vec<i32>) -> i32 {
31+
let base = 13331i64;
32+
let mod_val = 998244353i64;
33+
let inf = i32::MAX / 2;
34+
let n = target.len();
35+
let hashing = Hashing::new(&target, base, mod_val);
36+
37+
let mut f = vec![inf; n + 1];
38+
f[0] = 0;
39+
40+
let mut ss = BTreeSet::new();
41+
for w in &words {
42+
ss.insert(w.len());
43+
}
44+
45+
let mut d = HashMap::new();
46+
for i in 0..words.len() {
47+
let mut x = 0i64;
48+
for c in words[i].bytes() {
49+
x = (x * base + c as i64) % mod_val;
50+
}
51+
let entry = d.entry(x).or_insert(inf);
52+
*entry = min(*entry, costs[i]);
53+
}
54+
55+
for i in 1..=n {
56+
for &j in &ss {
57+
if j > i {
58+
break;
59+
}
60+
let x = hashing.query(i - j + 1, i);
61+
if let Some(&cost) = d.get(&x) {
62+
f[i] = min(f[i], f[i - j] + cost);
63+
}
64+
}
65+
}
66+
67+
if f[n] >= inf { -1 } else { f[n] }
68+
}
69+
}

0 commit comments

Comments
 (0)