Skip to content

Commit f831ff7

Browse files
committed
feat: add rust solutions to lc problem: No.3292
1 parent d24b952 commit f831ff7

File tree

4 files changed

+500
-0
lines changed

4 files changed

+500
-0
lines changed

solution/3200-3299/3292.Minimum Number of Valid Strings to Form Target II/README.md

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,176 @@ func minValidStrings(words []string, target string) (ans int) {
402402
}
403403
```
404404

405+
#### TypeScript
406+
407+
```ts
408+
function minValidStrings(words: string[], target: string): number {
409+
class Hashing {
410+
private p: bigint[];
411+
private h: bigint[];
412+
private mod: bigint;
413+
414+
constructor(word: string, base: bigint, mod: bigint) {
415+
const n = word.length;
416+
this.p = new Array<bigint>(n + 1).fill(0n);
417+
this.h = new Array<bigint>(n + 1).fill(0n);
418+
this.mod = mod;
419+
this.p[0] = 1n;
420+
for (let i = 1; i <= n; ++i) {
421+
this.p[i] = (this.p[i - 1] * base) % mod;
422+
this.h[i] = (this.h[i - 1] * base + BigInt(word.charCodeAt(i - 1))) % mod;
423+
}
424+
}
425+
426+
query(l: number, r: number): bigint {
427+
const res =
428+
(this.h[r] - ((this.h[l - 1] * this.p[r - l + 1]) % this.mod) + this.mod) %
429+
this.mod;
430+
return res;
431+
}
432+
}
433+
434+
const base = 13331n;
435+
const mod = 998244353n;
436+
const hashing = new Hashing(target, base, mod);
437+
438+
const m = Math.max(0, ...words.map(w => w.length));
439+
const s: Set<bigint>[] = Array.from({ length: m + 1 }, () => new Set<bigint>());
440+
441+
for (const w of words) {
442+
let h = 0n;
443+
for (let j = 0; j < w.length; ++j) {
444+
h = (h * base + BigInt(w.charCodeAt(j))) % mod;
445+
s[j + 1].add(h);
446+
}
447+
}
448+
449+
const n = target.length;
450+
let ans = 0;
451+
let last = 0;
452+
let mx = 0;
453+
454+
const f = (i: number): number => {
455+
let l = 0;
456+
let r = Math.min(n - i, m);
457+
while (l < r) {
458+
const mid = (l + r + 1) >> 1;
459+
const sub = hashing.query(i + 1, i + mid);
460+
if (s[mid].has(sub)) {
461+
l = mid;
462+
} else {
463+
r = mid - 1;
464+
}
465+
}
466+
return l;
467+
};
468+
469+
for (let i = 0; i < n; ++i) {
470+
const dist = f(i);
471+
mx = Math.max(mx, i + dist);
472+
if (i === last) {
473+
if (i === mx) {
474+
return -1;
475+
}
476+
last = mx;
477+
ans++;
478+
}
479+
}
480+
481+
return ans;
482+
}
483+
```
484+
485+
#### Rust
486+
487+
```rust
488+
use std::collections::HashSet;
489+
use std::cmp::max;
490+
491+
struct Hashing {
492+
p: Vec<i64>,
493+
h: Vec<i64>,
494+
base: i64,
495+
modv: i64,
496+
}
497+
498+
impl Hashing {
499+
fn new(word: &str, base: i64, modv: i64) -> Self {
500+
let n = word.len();
501+
let mut p = vec![0; n + 1];
502+
let mut h = vec![0; n + 1];
503+
let bytes = word.as_bytes();
504+
p[0] = 1;
505+
for i in 1..=n {
506+
p[i] = p[i - 1] * base % modv;
507+
h[i] = (h[i - 1] * base + bytes[i - 1] as i64) % modv;
508+
}
509+
Self { p, h, base, modv }
510+
}
511+
512+
fn query(&self, l: usize, r: usize) -> i64 {
513+
let mut res = self.h[r] - self.h[l - 1] * self.p[r - l + 1] % self.modv;
514+
if res < 0 {
515+
res += self.modv;
516+
}
517+
res % self.modv
518+
}
519+
}
520+
521+
impl Solution {
522+
pub fn min_valid_strings(words: Vec<String>, target: String) -> i32 {
523+
let base = 13331;
524+
let modv = 998_244_353;
525+
let hashing = Hashing::new(&target, base, modv);
526+
let m = words.iter().map(|w| w.len()).max().unwrap_or(0);
527+
let mut s: Vec<HashSet<i64>> = vec![HashSet::new(); m + 1];
528+
529+
for w in &words {
530+
let mut h = 0i64;
531+
for (j, &b) in w.as_bytes().iter().enumerate() {
532+
h = (h * base + b as i64) % modv;
533+
s[j + 1].insert(h);
534+
}
535+
}
536+
537+
let n = target.len();
538+
let bytes = target.as_bytes();
539+
let mut ans = 0;
540+
let mut last = 0;
541+
let mut mx = 0;
542+
543+
let f = |i: usize, n: usize, m: usize, s: &Vec<HashSet<i64>>, hashing: &Hashing| -> usize {
544+
let mut l = 0;
545+
let mut r = std::cmp::min(n - i, m);
546+
while l < r {
547+
let mid = (l + r + 1) >> 1;
548+
let sub = hashing.query(i + 1, i + mid);
549+
if s[mid].contains(&sub) {
550+
l = mid;
551+
} else {
552+
r = mid - 1;
553+
}
554+
}
555+
l
556+
};
557+
558+
for i in 0..n {
559+
let dist = f(i, n, m, &s, &hashing);
560+
mx = max(mx, i + dist);
561+
if i == last {
562+
if i == mx {
563+
return -1;
564+
}
565+
last = mx;
566+
ans += 1;
567+
}
568+
}
569+
570+
ans
571+
}
572+
}
573+
```
574+
405575
<!-- tabs:end -->
406576

407577
<!-- solution:end -->

solution/3200-3299/3292.Minimum Number of Valid Strings to Form Target II/README_EN.md

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,176 @@ func minValidStrings(words []string, target string) (ans int) {
400400
}
401401
```
402402

403+
#### TypeScript
404+
405+
```ts
406+
function minValidStrings(words: string[], target: string): number {
407+
class Hashing {
408+
private p: bigint[];
409+
private h: bigint[];
410+
private mod: bigint;
411+
412+
constructor(word: string, base: bigint, mod: bigint) {
413+
const n = word.length;
414+
this.p = new Array<bigint>(n + 1).fill(0n);
415+
this.h = new Array<bigint>(n + 1).fill(0n);
416+
this.mod = mod;
417+
this.p[0] = 1n;
418+
for (let i = 1; i <= n; ++i) {
419+
this.p[i] = (this.p[i - 1] * base) % mod;
420+
this.h[i] = (this.h[i - 1] * base + BigInt(word.charCodeAt(i - 1))) % mod;
421+
}
422+
}
423+
424+
query(l: number, r: number): bigint {
425+
const res =
426+
(this.h[r] - ((this.h[l - 1] * this.p[r - l + 1]) % this.mod) + this.mod) %
427+
this.mod;
428+
return res;
429+
}
430+
}
431+
432+
const base = 13331n;
433+
const mod = 998244353n;
434+
const hashing = new Hashing(target, base, mod);
435+
436+
const m = Math.max(0, ...words.map(w => w.length));
437+
const s: Set<bigint>[] = Array.from({ length: m + 1 }, () => new Set<bigint>());
438+
439+
for (const w of words) {
440+
let h = 0n;
441+
for (let j = 0; j < w.length; ++j) {
442+
h = (h * base + BigInt(w.charCodeAt(j))) % mod;
443+
s[j + 1].add(h);
444+
}
445+
}
446+
447+
const n = target.length;
448+
let ans = 0;
449+
let last = 0;
450+
let mx = 0;
451+
452+
const f = (i: number): number => {
453+
let l = 0;
454+
let r = Math.min(n - i, m);
455+
while (l < r) {
456+
const mid = (l + r + 1) >> 1;
457+
const sub = hashing.query(i + 1, i + mid);
458+
if (s[mid].has(sub)) {
459+
l = mid;
460+
} else {
461+
r = mid - 1;
462+
}
463+
}
464+
return l;
465+
};
466+
467+
for (let i = 0; i < n; ++i) {
468+
const dist = f(i);
469+
mx = Math.max(mx, i + dist);
470+
if (i === last) {
471+
if (i === mx) {
472+
return -1;
473+
}
474+
last = mx;
475+
ans++;
476+
}
477+
}
478+
479+
return ans;
480+
}
481+
```
482+
483+
#### Rust
484+
485+
```rust
486+
use std::collections::HashSet;
487+
use std::cmp::max;
488+
489+
struct Hashing {
490+
p: Vec<i64>,
491+
h: Vec<i64>,
492+
base: i64,
493+
modv: i64,
494+
}
495+
496+
impl Hashing {
497+
fn new(word: &str, base: i64, modv: i64) -> Self {
498+
let n = word.len();
499+
let mut p = vec![0; n + 1];
500+
let mut h = vec![0; n + 1];
501+
let bytes = word.as_bytes();
502+
p[0] = 1;
503+
for i in 1..=n {
504+
p[i] = p[i - 1] * base % modv;
505+
h[i] = (h[i - 1] * base + bytes[i - 1] as i64) % modv;
506+
}
507+
Self { p, h, base, modv }
508+
}
509+
510+
fn query(&self, l: usize, r: usize) -> i64 {
511+
let mut res = self.h[r] - self.h[l - 1] * self.p[r - l + 1] % self.modv;
512+
if res < 0 {
513+
res += self.modv;
514+
}
515+
res % self.modv
516+
}
517+
}
518+
519+
impl Solution {
520+
pub fn min_valid_strings(words: Vec<String>, target: String) -> i32 {
521+
let base = 13331;
522+
let modv = 998_244_353;
523+
let hashing = Hashing::new(&target, base, modv);
524+
let m = words.iter().map(|w| w.len()).max().unwrap_or(0);
525+
let mut s: Vec<HashSet<i64>> = vec![HashSet::new(); m + 1];
526+
527+
for w in &words {
528+
let mut h = 0i64;
529+
for (j, &b) in w.as_bytes().iter().enumerate() {
530+
h = (h * base + b as i64) % modv;
531+
s[j + 1].insert(h);
532+
}
533+
}
534+
535+
let n = target.len();
536+
let bytes = target.as_bytes();
537+
let mut ans = 0;
538+
let mut last = 0;
539+
let mut mx = 0;
540+
541+
let f = |i: usize, n: usize, m: usize, s: &Vec<HashSet<i64>>, hashing: &Hashing| -> usize {
542+
let mut l = 0;
543+
let mut r = std::cmp::min(n - i, m);
544+
while l < r {
545+
let mid = (l + r + 1) >> 1;
546+
let sub = hashing.query(i + 1, i + mid);
547+
if s[mid].contains(&sub) {
548+
l = mid;
549+
} else {
550+
r = mid - 1;
551+
}
552+
}
553+
l
554+
};
555+
556+
for i in 0..n {
557+
let dist = f(i, n, m, &s, &hashing);
558+
mx = max(mx, i + dist);
559+
if i == last {
560+
if i == mx {
561+
return -1;
562+
}
563+
last = mx;
564+
ans += 1;
565+
}
566+
}
567+
568+
ans
569+
}
570+
}
571+
```
572+
403573
<!-- tabs:end -->
404574

405575
<!-- solution:end -->

0 commit comments

Comments
 (0)