From 3f9b489f0277aebe45909ae9f27f5ffa93d3789e Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Sun, 4 Feb 2024 21:00:17 +0800 Subject: [PATCH] feat: add solutions to lc problem: No.3031 (#2317) No.3031.Minimum Time to Revert Word to Initial State II --- .../README.md | 140 +++++++++++++++++- .../README_EN.md | 130 +++++++++++++++- .../Solution.cpp | 37 +++++ .../Solution.go | 32 ++++ .../Solution.java | 34 +++++ .../Solution.py | 23 +++ 6 files changed, 387 insertions(+), 9 deletions(-) create mode 100644 solution/3000-3099/3031.Minimum Time to Revert Word to Initial State II/Solution.cpp create mode 100644 solution/3000-3099/3031.Minimum Time to Revert Word to Initial State II/Solution.go create mode 100644 solution/3000-3099/3031.Minimum Time to Revert Word to Initial State II/Solution.java create mode 100644 solution/3000-3099/3031.Minimum Time to Revert Word to Initial State II/Solution.py diff --git a/solution/3000-3099/3031.Minimum Time to Revert Word to Initial State II/README.md b/solution/3000-3099/3031.Minimum Time to Revert Word to Initial State II/README.md index 256a80177178b..fe8928174e104 100644 --- a/solution/3000-3099/3031.Minimum Time to Revert Word to Initial State II/README.md +++ b/solution/3000-3099/3031.Minimum Time to Revert Word to Initial State II/README.md @@ -65,24 +65,154 @@ ## 解法 -### 方法一 +### 方法一:枚举 + 字符串哈希 + +我们不妨假设,如果只操作一次,就能使得 `word` 恢复到初始状态,那么意味着 `word[k:]` 是 `word` 的前缀,即 `word[k:] == word[:n-k]`。 + +如果有多次操作,不妨设 $i$ 为操作次数,那么意味着 `word[k*i:]` 是 `word` 的前缀,即 `word[k*i:] == word[:n-k*i]`。 + +因此,我们可以枚举操作次数,利用字符串哈希来判断两个字符串是否相等。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为 `word` 的长度。 ```python - +class Hashing: + __slots__ = ["mod", "h", "p"] + + def __init__(self, s: str, base: int, mod: int): + self.mod = mod + self.h = [0] * (len(s) + 1) + self.p = [1] * (len(s) + 1) + for i in range(1, len(s) + 1): + self.h[i] = (self.h[i - 1] * base + ord(s[i - 1])) % mod + self.p[i] = (self.p[i - 1] * base) % mod + + def query(self, l: int, r: int) -> int: + return (self.h[r] - self.h[l - 1] * self.p[r - l + 1]) % self.mod + + +class Solution: + def minimumTimeToInitialState(self, word: str, k: int) -> int: + hashing = Hashing(word, 13331, 998244353) + n = len(word) + for i in range(k, n, k): + if hashing.query(1, n - i) == hashing.query(i + 1, n): + return i // k + return (n + k - 1) // k ``` ```java - +class Hashing { + private final long[] p; + private final long[] h; + private final long mod; + + public Hashing(String word, long base, int mod) { + int n = word.length(); + p = new long[n + 1]; + h = new long[n + 1]; + p[0] = 1; + this.mod = mod; + for (int i = 1; i <= n; i++) { + p[i] = p[i - 1] * base % mod; + h[i] = (h[i - 1] * base + word.charAt(i - 1) - 'a') % mod; + } + } + + public long query(int l, int r) { + return (h[r] - h[l - 1] * p[r - l + 1] % mod + mod) % mod; + } +} + +class Solution { + public int minimumTimeToInitialState(String word, int k) { + Hashing hashing = new Hashing(word, 13331, 998244353); + int n = word.length(); + for (int i = k; i < n; i += k) { + if (hashing.query(1, n - i) == hashing.query(i + 1, n)) { + return i / k; + } + } + return (n + k - 1) / k; + } +} ``` ```cpp - +class Hashing { +private: + vector p; + vector h; + long long mod; + +public: + Hashing(string word, long long base, int mod) { + int n = word.size(); + p.resize(n + 1); + h.resize(n + 1); + p[0] = 1; + this->mod = mod; + for (int i = 1; i <= n; i++) { + p[i] = (p[i - 1] * base) % mod; + h[i] = (h[i - 1] * base + word[i - 1] - 'a') % mod; + } + } + + long long query(int l, int r) { + return (h[r] - h[l - 1] * p[r - l + 1] % mod + mod) % mod; + } +}; + +class Solution { +public: + int minimumTimeToInitialState(string word, int k) { + Hashing hashing(word, 13331, 998244353); + int n = word.size(); + for (int i = k; i < n; i += k) { + if (hashing.query(1, n - i) == hashing.query(i + 1, n)) { + return i / k; + } + } + return (n + k - 1) / k; + } +}; ``` ```go - +type Hashing struct { + p []int64 + h []int64 + mod int64 +} + +func NewHashing(word string, base int64, 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]-'a')) % mod + } + return &Hashing{p, h, mod} +} + +func (hashing *Hashing) Query(l, r int) int64 { + return (hashing.h[r] - hashing.h[l-1]*hashing.p[r-l+1]%hashing.mod + hashing.mod) % hashing.mod +} + +func minimumTimeToInitialState(word string, k int) int { + hashing := NewHashing(word, 13331, 998244353) + n := len(word) + for i := k; i < n; i += k { + if hashing.Query(1, n-i) == hashing.Query(i+1, n) { + return i / k + } + } + return (n + k - 1) / k +} ``` diff --git a/solution/3000-3099/3031.Minimum Time to Revert Word to Initial State II/README_EN.md b/solution/3000-3099/3031.Minimum Time to Revert Word to Initial State II/README_EN.md index d0ccf962dbc77..174171bd99304 100644 --- a/solution/3000-3099/3031.Minimum Time to Revert Word to Initial State II/README_EN.md +++ b/solution/3000-3099/3031.Minimum Time to Revert Word to Initial State II/README_EN.md @@ -63,19 +63,141 @@ It can be shown that 4 seconds is the minimum time greater than zero required fo ```python - +class Hashing: + __slots__ = ["mod", "h", "p"] + + def __init__(self, s: str, base: int, mod: int): + self.mod = mod + self.h = [0] * (len(s) + 1) + self.p = [1] * (len(s) + 1) + for i in range(1, len(s) + 1): + self.h[i] = (self.h[i - 1] * base + ord(s[i - 1])) % mod + self.p[i] = (self.p[i - 1] * base) % mod + + def query(self, l: int, r: int) -> int: + return (self.h[r] - self.h[l - 1] * self.p[r - l + 1]) % self.mod + + +class Solution: + def minimumTimeToInitialState(self, word: str, k: int) -> int: + hashing = Hashing(word, 13331, 998244353) + n = len(word) + for i in range(k, n, k): + if hashing.query(1, n - i) == hashing.query(i + 1, n): + return i // k + return (n + k - 1) // k ``` ```java - +class Hashing { + private final long[] p; + private final long[] h; + private final long mod; + + public Hashing(String word, long base, int mod) { + int n = word.length(); + p = new long[n + 1]; + h = new long[n + 1]; + p[0] = 1; + this.mod = mod; + for (int i = 1; i <= n; i++) { + p[i] = p[i - 1] * base % mod; + h[i] = (h[i - 1] * base + word.charAt(i - 1) - 'a') % mod; + } + } + + public long query(int l, int r) { + return (h[r] - h[l - 1] * p[r - l + 1] % mod + mod) % mod; + } +} + +class Solution { + public int minimumTimeToInitialState(String word, int k) { + Hashing hashing = new Hashing(word, 13331, 998244353); + int n = word.length(); + for (int i = k; i < n; i += k) { + if (hashing.query(1, n - i) == hashing.query(i + 1, n)) { + return i / k; + } + } + return (n + k - 1) / k; + } +} ``` ```cpp - +class Hashing { +private: + vector p; + vector h; + long long mod; + +public: + Hashing(string word, long long base, int mod) { + int n = word.size(); + p.resize(n + 1); + h.resize(n + 1); + p[0] = 1; + this->mod = mod; + for (int i = 1; i <= n; i++) { + p[i] = (p[i - 1] * base) % mod; + h[i] = (h[i - 1] * base + word[i - 1] - 'a') % mod; + } + } + + long long query(int l, int r) { + return (h[r] - h[l - 1] * p[r - l + 1] % mod + mod) % mod; + } +}; + +class Solution { +public: + int minimumTimeToInitialState(string word, int k) { + Hashing hashing(word, 13331, 998244353); + int n = word.size(); + for (int i = k; i < n; i += k) { + if (hashing.query(1, n - i) == hashing.query(i + 1, n)) { + return i / k; + } + } + return (n + k - 1) / k; + } +}; ``` ```go - +type Hashing struct { + p []int64 + h []int64 + mod int64 +} + +func NewHashing(word string, base int64, 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]-'a')) % mod + } + return &Hashing{p, h, mod} +} + +func (hashing *Hashing) Query(l, r int) int64 { + return (hashing.h[r] - hashing.h[l-1]*hashing.p[r-l+1]%hashing.mod + hashing.mod) % hashing.mod +} + +func minimumTimeToInitialState(word string, k int) int { + hashing := NewHashing(word, 13331, 998244353) + n := len(word) + for i := k; i < n; i += k { + if hashing.Query(1, n-i) == hashing.Query(i+1, n) { + return i / k + } + } + return (n + k - 1) / k +} ``` diff --git a/solution/3000-3099/3031.Minimum Time to Revert Word to Initial State II/Solution.cpp b/solution/3000-3099/3031.Minimum Time to Revert Word to Initial State II/Solution.cpp new file mode 100644 index 0000000000000..2dba674589f45 --- /dev/null +++ b/solution/3000-3099/3031.Minimum Time to Revert Word to Initial State II/Solution.cpp @@ -0,0 +1,37 @@ +class Hashing { +private: + vector p; + vector h; + long long mod; + +public: + Hashing(string word, long long base, int mod) { + int n = word.size(); + p.resize(n + 1); + h.resize(n + 1); + p[0] = 1; + this->mod = mod; + for (int i = 1; i <= n; i++) { + p[i] = (p[i - 1] * base) % mod; + h[i] = (h[i - 1] * base + word[i - 1] - 'a') % mod; + } + } + + long long query(int l, int r) { + return (h[r] - h[l - 1] * p[r - l + 1] % mod + mod) % mod; + } +}; + +class Solution { +public: + int minimumTimeToInitialState(string word, int k) { + Hashing hashing(word, 13331, 998244353); + int n = word.size(); + for (int i = k; i < n; i += k) { + if (hashing.query(1, n - i) == hashing.query(i + 1, n)) { + return i / k; + } + } + return (n + k - 1) / k; + } +}; \ No newline at end of file diff --git a/solution/3000-3099/3031.Minimum Time to Revert Word to Initial State II/Solution.go b/solution/3000-3099/3031.Minimum Time to Revert Word to Initial State II/Solution.go new file mode 100644 index 0000000000000..7d7a097a7352c --- /dev/null +++ b/solution/3000-3099/3031.Minimum Time to Revert Word to Initial State II/Solution.go @@ -0,0 +1,32 @@ +type Hashing struct { + p []int64 + h []int64 + mod int64 +} + +func NewHashing(word string, base int64, 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]-'a')) % mod + } + return &Hashing{p, h, mod} +} + +func (hashing *Hashing) Query(l, r int) int64 { + return (hashing.h[r] - hashing.h[l-1]*hashing.p[r-l+1]%hashing.mod + hashing.mod) % hashing.mod +} + +func minimumTimeToInitialState(word string, k int) int { + hashing := NewHashing(word, 13331, 998244353) + n := len(word) + for i := k; i < n; i += k { + if hashing.Query(1, n-i) == hashing.Query(i+1, n) { + return i / k + } + } + return (n + k - 1) / k +} \ No newline at end of file diff --git a/solution/3000-3099/3031.Minimum Time to Revert Word to Initial State II/Solution.java b/solution/3000-3099/3031.Minimum Time to Revert Word to Initial State II/Solution.java new file mode 100644 index 0000000000000..6b315cb015714 --- /dev/null +++ b/solution/3000-3099/3031.Minimum Time to Revert Word to Initial State II/Solution.java @@ -0,0 +1,34 @@ +class Hashing { + private final long[] p; + private final long[] h; + private final long mod; + + public Hashing(String word, long base, int mod) { + int n = word.length(); + p = new long[n + 1]; + h = new long[n + 1]; + p[0] = 1; + this.mod = mod; + for (int i = 1; i <= n; i++) { + p[i] = p[i - 1] * base % mod; + h[i] = (h[i - 1] * base + word.charAt(i - 1) - 'a') % mod; + } + } + + public long query(int l, int r) { + return (h[r] - h[l - 1] * p[r - l + 1] % mod + mod) % mod; + } +} + +class Solution { + public int minimumTimeToInitialState(String word, int k) { + Hashing hashing = new Hashing(word, 13331, 998244353); + int n = word.length(); + for (int i = k; i < n; i += k) { + if (hashing.query(1, n - i) == hashing.query(i + 1, n)) { + return i / k; + } + } + return (n + k - 1) / k; + } +} \ No newline at end of file diff --git a/solution/3000-3099/3031.Minimum Time to Revert Word to Initial State II/Solution.py b/solution/3000-3099/3031.Minimum Time to Revert Word to Initial State II/Solution.py new file mode 100644 index 0000000000000..edbb9163bc8ed --- /dev/null +++ b/solution/3000-3099/3031.Minimum Time to Revert Word to Initial State II/Solution.py @@ -0,0 +1,23 @@ +class Hashing: + __slots__ = ["mod", "h", "p"] + + def __init__(self, s: str, base: int, mod: int): + self.mod = mod + self.h = [0] * (len(s) + 1) + self.p = [1] * (len(s) + 1) + for i in range(1, len(s) + 1): + self.h[i] = (self.h[i - 1] * base + ord(s[i - 1])) % mod + self.p[i] = (self.p[i - 1] * base) % mod + + def query(self, l: int, r: int) -> int: + return (self.h[r] - self.h[l - 1] * self.p[r - l + 1]) % self.mod + + +class Solution: + def minimumTimeToInitialState(self, word: str, k: int) -> int: + hashing = Hashing(word, 13331, 998244353) + n = len(word) + for i in range(k, n, k): + if hashing.query(1, n - i) == hashing.query(i + 1, n): + return i // k + return (n + k - 1) // k