From 79149ea4d95f2efe6349d37b4e6b34aaa3ee07e1 Mon Sep 17 00:00:00 2001 From: Hiren Thakore Date: Sun, 24 Sep 2023 18:38:34 -0400 Subject: [PATCH 1/7] added solutions to 2867 Count valid paths in a tree --- .../Solution.cpp | 53 ++++++++++++++ .../Solution.java | 69 +++++++++++++++++++ .../Solution.py | 42 +++++++++++ 3 files changed, 164 insertions(+) create mode 100644 solution/2800-2899/2867.Count Valid Paths in a Tree/Solution.cpp create mode 100644 solution/2800-2899/2867.Count Valid Paths in a Tree/Solution.java create mode 100644 solution/2800-2899/2867.Count Valid Paths in a Tree/Solution.py diff --git a/solution/2800-2899/2867.Count Valid Paths in a Tree/Solution.cpp b/solution/2800-2899/2867.Count Valid Paths in a Tree/Solution.cpp new file mode 100644 index 0000000000000..18042eab1cd55 --- /dev/null +++ b/solution/2800-2899/2867.Count Valid Paths in a Tree/Solution.cpp @@ -0,0 +1,53 @@ +class Solution { + long long mul(long long x, long long y) { + return x * y; + } + + pair dfs(int x, int f, const vector> &con, const vector &prime, long long &r) { + pair v = {!prime[x], prime[x]}; + for (int y : con[x]) { + if (y == f) continue; + const auto& p = dfs(y, x, con, prime, r); + r += mul(p.first, v.second) + mul(p.second, v.first); + if (prime[x]) { + v.second += p.first; + } else { + v.first += p.first; + v.second += p.second; + } + + } + return v; + } + +public: + long long countPaths(int n, vector>& edges) { + vector prime(n + 1, true); + prime[1] = false; + vector all; + for (int i = 2; i <= n; ++i) { + if (prime[i]) { + all.push_back(i); + } + for (int x : all) { + const int temp = i * x; + if (temp > n) { + break; + } + prime[temp] = false; + if (i % x == 0) { + break; + } + } + } + vector> con(n + 1); + for (const auto& e : edges) { + con[e[0]].push_back(e[1]); + con[e[1]].push_back(e[0]); + } + long long r = 0; + dfs(1, 0, con, prime, r); + return r; + + } +}; \ No newline at end of file diff --git a/solution/2800-2899/2867.Count Valid Paths in a Tree/Solution.java b/solution/2800-2899/2867.Count Valid Paths in a Tree/Solution.java new file mode 100644 index 0000000000000..241fd7ef07373 --- /dev/null +++ b/solution/2800-2899/2867.Count Valid Paths in a Tree/Solution.java @@ -0,0 +1,69 @@ +class Solution { + public long countPaths(int n, int[][] edges) { + List prime = new ArrayList<>(n + 1); + for (int i = 0; i <= n; ++i) { + prime.add(true); + } + prime.set(1, false); + + List all = new ArrayList<>(); + for (int i = 2; i <= n; ++i) { + if (prime.get(i)) { + all.add(i); + } + for (int x : all) { + int temp = i * x; + if (temp > n) { + break; + } + prime.set(temp, false); + if (i % x == 0) { + break; + } + } + } + + List> con = new ArrayList<>(n + 1); + for (int i = 0; i <= n; ++i) { + con.add(new ArrayList<>()); + } + for (int[] e : edges) { + con.get(e[0]).add(e[1]); + con.get(e[1]).add(e[0]); + } + + long[] r = {0}; + dfs(1, 0, con, prime, r); + return r[0]; + } + + private long mul(long x, long y) { + return x * y; + } + + private class Pair { + int first; + int second; + + Pair(int first, int second) { + this.first = first; + this.second = second; + } + } + + private Pair dfs(int x, int f, List> con, List prime, long[] r) { + Pair v = new Pair(!prime.get(x) ? 1 : 0, prime.get(x) ? 1 : 0); + for (int y : con.get(x)) { + if (y == f) continue; + Pair p = dfs(y, x, con, prime, r); + r[0] += mul(p.first, v.second) + mul(p.second, v.first); + if (prime.get(x)) { + v.second += p.first; + } else { + v.first += p.first; + v.second += p.second; + } + } + return v; + } +} \ No newline at end of file diff --git a/solution/2800-2899/2867.Count Valid Paths in a Tree/Solution.py b/solution/2800-2899/2867.Count Valid Paths in a Tree/Solution.py new file mode 100644 index 0000000000000..d438ea49c8cb8 --- /dev/null +++ b/solution/2800-2899/2867.Count Valid Paths in a Tree/Solution.py @@ -0,0 +1,42 @@ +class Solution: + def countPaths(self, n: int, edges: List[List[int]]) -> int: + def mul(x, y): + return x * y + + def dfs(x, f, con, prime, r): + v = [1 - prime[x], prime[x]] + for y in con[x]: + if y == f: + continue + p = dfs(y, x, con, prime, r) + r[0] += mul(p[0], v[1]) + mul(p[1], v[0]) + if prime[x]: + v[1] += p[0] + else: + v[0] += p[0] + v[1] += p[1] + return v + + prime = [True] * (n + 1) + prime[1] = False + + all_primes = [] + for i in range(2, n + 1): + if prime[i]: + all_primes.append(i) + for x in all_primes: + temp = i * x + if temp > n: + break + prime[temp] = False + if i % x == 0: + break + + con = [[] for _ in range(n + 1)] + for e in edges: + con[e[0]].append(e[1]) + con[e[1]].append(e[0]) + + r = [0] + dfs(1, 0, con, prime, r) + return r[0] \ No newline at end of file From c60314f8fa6d05df1f06dd12aafd68565f6f5c67 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Mon, 25 Sep 2023 07:47:12 +0800 Subject: [PATCH 2/7] style: format py code --- .../2867.Count Valid Paths in a Tree/Solution.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/solution/2800-2899/2867.Count Valid Paths in a Tree/Solution.py b/solution/2800-2899/2867.Count Valid Paths in a Tree/Solution.py index d438ea49c8cb8..51e89eeefa99f 100644 --- a/solution/2800-2899/2867.Count Valid Paths in a Tree/Solution.py +++ b/solution/2800-2899/2867.Count Valid Paths in a Tree/Solution.py @@ -2,7 +2,7 @@ class Solution: def countPaths(self, n: int, edges: List[List[int]]) -> int: def mul(x, y): return x * y - + def dfs(x, f, con, prime, r): v = [1 - prime[x], prime[x]] for y in con[x]: @@ -16,10 +16,10 @@ def dfs(x, f, con, prime, r): v[0] += p[0] v[1] += p[1] return v - + prime = [True] * (n + 1) prime[1] = False - + all_primes = [] for i in range(2, n + 1): if prime[i]: @@ -31,12 +31,12 @@ def dfs(x, f, con, prime, r): prime[temp] = False if i % x == 0: break - + con = [[] for _ in range(n + 1)] for e in edges: con[e[0]].append(e[1]) con[e[1]].append(e[0]) - + r = [0] dfs(1, 0, con, prime, r) - return r[0] \ No newline at end of file + return r[0] From eff0e1ee5153a708d1db157ba874654486037bdd Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Mon, 25 Sep 2023 07:47:58 +0800 Subject: [PATCH 3/7] style: format java code --- .../Solution.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/solution/2800-2899/2867.Count Valid Paths in a Tree/Solution.java b/solution/2800-2899/2867.Count Valid Paths in a Tree/Solution.java index 241fd7ef07373..c727227b6bb8d 100644 --- a/solution/2800-2899/2867.Count Valid Paths in a Tree/Solution.java +++ b/solution/2800-2899/2867.Count Valid Paths in a Tree/Solution.java @@ -5,7 +5,7 @@ public long countPaths(int n, int[][] edges) { prime.add(true); } prime.set(1, false); - + List all = new ArrayList<>(); for (int i = 2; i <= n; ++i) { if (prime.get(i)) { @@ -22,7 +22,7 @@ public long countPaths(int n, int[][] edges) { } } } - + List> con = new ArrayList<>(n + 1); for (int i = 0; i <= n; ++i) { con.add(new ArrayList<>()); @@ -31,26 +31,26 @@ public long countPaths(int n, int[][] edges) { con.get(e[0]).add(e[1]); con.get(e[1]).add(e[0]); } - + long[] r = {0}; dfs(1, 0, con, prime, r); return r[0]; } - + private long mul(long x, long y) { return x * y; } - + private class Pair { int first; int second; - + Pair(int first, int second) { this.first = first; this.second = second; } } - + private Pair dfs(int x, int f, List> con, List prime, long[] r) { Pair v = new Pair(!prime.get(x) ? 1 : 0, prime.get(x) ? 1 : 0); for (int y : con.get(x)) { @@ -66,4 +66,4 @@ private Pair dfs(int x, int f, List> con, List prime, lon } return v; } -} \ No newline at end of file +} From 2bc06aca6de5207053ab15f529dd5a44349a53e9 Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Mon, 25 Sep 2023 07:48:52 +0800 Subject: [PATCH 4/7] style: format cpp code --- .../2867.Count Valid Paths in a Tree/Solution.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/solution/2800-2899/2867.Count Valid Paths in a Tree/Solution.cpp b/solution/2800-2899/2867.Count Valid Paths in a Tree/Solution.cpp index 18042eab1cd55..61cda58e24057 100644 --- a/solution/2800-2899/2867.Count Valid Paths in a Tree/Solution.cpp +++ b/solution/2800-2899/2867.Count Valid Paths in a Tree/Solution.cpp @@ -2,8 +2,8 @@ class Solution { long long mul(long long x, long long y) { return x * y; } - - pair dfs(int x, int f, const vector> &con, const vector &prime, long long &r) { + + pair dfs(int x, int f, const vector>& con, const vector& prime, long long& r) { pair v = {!prime[x], prime[x]}; for (int y : con[x]) { if (y == f) continue; @@ -15,11 +15,10 @@ class Solution { v.first += p.first; v.second += p.second; } - } return v; } - + public: long long countPaths(int n, vector>& edges) { vector prime(n + 1, true); @@ -37,7 +36,7 @@ class Solution { prime[temp] = false; if (i % x == 0) { break; - } + } } } vector> con(n + 1); @@ -48,6 +47,5 @@ class Solution { long long r = 0; dfs(1, 0, con, prime, r); return r; - } -}; \ No newline at end of file +}; From bf566317f22cb8139542808dfb5beb3259d1db59 Mon Sep 17 00:00:00 2001 From: Hiren Thakore Date: Sun, 24 Sep 2023 21:29:37 -0400 Subject: [PATCH 5/7] added solutions to 2851 String Transformation --- .../2851.String Transformation/Solution.cpp | 79 ++++++++++++ .../2851.String Transformation/Solution.java | 83 +++++++++++++ .../2851.String Transformation/Solution.py | 117 ++++++++++++++++++ 3 files changed, 279 insertions(+) create mode 100644 solution/2800-2899/2851.String Transformation/Solution.cpp create mode 100644 solution/2800-2899/2851.String Transformation/Solution.java create mode 100644 solution/2800-2899/2851.String Transformation/Solution.py diff --git a/solution/2800-2899/2851.String Transformation/Solution.cpp b/solution/2800-2899/2851.String Transformation/Solution.cpp new file mode 100644 index 0000000000000..fcf59f9fc0c5c --- /dev/null +++ b/solution/2800-2899/2851.String Transformation/Solution.cpp @@ -0,0 +1,79 @@ +class Solution { +const int M = 1000000007; + +int add(int x, int y) { + if ((x += y) >= M) { + x -= M; + } + return x; +} + +int mul(long long x, long long y) { + return x * y % M; +} + + +vector getz(const string& s) { + const int n = s.length(); + vector z(n); + for (int i = 1, left = 0, right = 0; i < n; ++i) { + if (i <= right && z[i - left] <= right - i) { + z[i] = z[i - left]; + } else { + for (z[i] = max(0, right - i + 1); i + z[i] < n && s[i + z[i]] == s[z[i]]; ++z[i]) + ; + } + if (i + z[i] - 1 > right) { + left = i; + right = i + z[i] - 1; + } + } + return z; +} + +vector> mul(const vector> &a, const vector> &b) { + const int m = a.size(), n = a[0].size(), p = b[0].size(); + vector> r(m, vector(p)); + for (int i = 0; i < m; ++i) { + for (int j = 0; j < n; ++j) { + for (int k = 0; k < p; ++k) { + r[i][k] = add(r[i][k], mul(a[i][j], b[j][k])); + } + } + } + return r; +} + +vector> pow(const vector> &a, long long y) { + const int n = a.size(); + vector> r(n, vector(n)); + for (int i = 0; i < n; ++i) { + r[i][i] = 1; + } + auto x = a; + for (; y; y >>= 1) { + if (y & 1) { + r = mul(r, x); + } + x = mul(x, x); + } + return r; +} + +public: + int numberOfWays(string s, string t, long long k) { + const int n = s.length(); + const auto dp = pow({{0, 1}, {n - 1, n - 2}}, k)[0]; + s.append(t); + s.append(t); + const auto z = getz(s); + const int m = n + n; + int r = 0; + for (int i = n; i < m; ++i) { + if (z[i] >= n) { + r = add(r, dp[!!(i - n)]); + } + } + return r; + } +}; \ No newline at end of file diff --git a/solution/2800-2899/2851.String Transformation/Solution.java b/solution/2800-2899/2851.String Transformation/Solution.java new file mode 100644 index 0000000000000..9139f8b0240c4 --- /dev/null +++ b/solution/2800-2899/2851.String Transformation/Solution.java @@ -0,0 +1,83 @@ +class Solution { + private static final int M = 1000000007; + + private int add(int x, int y) { + if ((x += y) >= M) { + x -= M; + } + return x; + } + + private int mul(long x, long y) { + return (int) (x * y % M); + } + + private int[] getZ(String s) { + int n = s.length(); + int[] z = new int[n]; + for (int i = 1, left = 0, right = 0; i < n; ++i) { + if (i <= right && z[i - left] <= right - i) { + z[i] = z[i - left]; + } else { + int z_i = Math.max(0, right - i + 1); + while (i + z_i < n && s.charAt(i + z_i) == s.charAt(z_i)) { + z_i++; + } + z[i] = z_i; + } + if (i + z[i] - 1 > right) { + left = i; + right = i + z[i] - 1; + } + } + return z; + } + + private int[][] matrixMultiply(int[][] a, int[][] b) { + int m = a.length, n = a[0].length, p = b[0].length; + int[][] r = new int[m][p]; + for (int i = 0; i < m; ++i) { + for (int j = 0; j < p; ++j) { + for (int k = 0; k < n; ++k) { + r[i][j] = add(r[i][j], mul(a[i][k], b[k][j])); + } + } + } + return r; + } + + private int[][] matrixPower(int[][] a, long y) { + int n = a.length; + int[][] r = new int[n][n]; + for (int i = 0; i < n; ++i) { + r[i][i] = 1; + } + int[][] x = new int[n][n]; + for (int i = 0; i < n; ++i) { + System.arraycopy(a[i], 0, x[i], 0, n); + } + while (y > 0) { + if ((y & 1) == 1) { + r = matrixMultiply(r, x); + } + x = matrixMultiply(x, x); + y >>= 1; + } + return r; + } + + public int numberOfWays(String s, String t, long k) { + int n = s.length(); + int[] dp = matrixPower(new int[][]{{0, 1}, {n - 1, n - 2}}, k)[0]; + s += t + t; + int[] z = getZ(s); + int m = n + n; + int result = 0; + for (int i = n; i < m; ++i) { + if (z[i] >= n) { + result = add(result, dp[i - n == 0 ? 0 : 1]); + } + } + return result; + } +} \ No newline at end of file diff --git a/solution/2800-2899/2851.String Transformation/Solution.py b/solution/2800-2899/2851.String Transformation/Solution.py new file mode 100644 index 0000000000000..878d8004772d9 --- /dev/null +++ b/solution/2800-2899/2851.String Transformation/Solution.py @@ -0,0 +1,117 @@ +''' +DP, Z-algorithm, Fast mod. + +Approach +How to represent a string? +Each operation is just a rotation. Each result string can be represented by an integer from 0 to n - 1. Namely, it's just the new index of s[0]. + +How to find the integer(s) that can represent string t? +Create a new string s + t + t (length = 3 * n). +Use Z-algorithm (or KMP), for each n <= index < 2 * n, calculate the maximum prefix length that each substring starts from index can match, if the length >= n, then (index - n) is a valid integer representation. + +How to get the result? +It's a very obvious DP. +If we use an integer to represent a string, we only need to consider the transition from zero to non-zero and from non-zero to zero. In other words, all the non-zero strings should have the same result. + +So let dp[t][i = 0/1] be the number of ways to get the zero/nonzero string +after excatly t steps. +Then +dp[t][0] = dp[t - 1][1] * (n - 1). +All the non zero strings can make it. + +dp[t][1] = dp[t - 1][0] + dp[t - 1] * (n - 2). +For a particular non zero string, all the other non zero strings and zero string can make it. + +We have dp[0][0] = 1 and dp[0][1] = 0 + +Use matrix multiplication. +How to calculate dp[k][x = 0, 1] faster? + +Use matrix multiplication + +vector (dp[t - 1][0], dp[t - 1][1]) + +multiplies matrix + +[0 1] +[n - 1 n - 2] + +== vector (dp[t][0], dp[t - 1][1]). + +So we just need to calculate the kth power of the matrix which can be done by fast power algorith. + +Complexity +Time complexity: +O(n + logk) + +Space complexity: +O(n) + +''' + + + +class Solution: + M: int = 1000000007 + + def add(self, x: int, y: int) -> int: + x += y + if x >= self.M: + x -= self.M + return x + + def mul(self, x: int, y: int) -> int: + return int(x * y % self.M) + + def getZ(self, s: str) -> List[int]: + n = len(s) + z = [0] * n + left = right = 0 + for i in range(1, n): + if i <= right and z[i - left] <= right - i: + z[i] = z[i - left] + else: + z_i = max(0, right - i + 1) + while i + z_i < n and s[i + z_i] == s[z_i]: + z_i += 1 + z[i] = z_i + if i + z[i] - 1 > right: + left = i + right = i + z[i] - 1 + return z + + def matrixMultiply(self, a: List[List[int]], b: List[List[int]]) -> List[List[int]]: + m = len(a) + n = len(a[0]) + p = len(b[0]) + r = [[0] * p for _ in range(m)] + for i in range(m): + for j in range(p): + for k in range(n): + r[i][j] = self.add(r[i][j], self.mul(a[i][k], b[k][j])) + return r + + def matrixPower(self, a: List[List[int]], y: int) -> List[List[int]]: + n = len(a) + r = [[0] * n for _ in range(n)] + for i in range(n): + r[i][i] = 1 + x = [a[i][:] for i in range(n)] + while y > 0: + if y & 1: + r = self.matrixMultiply(r, x) + x = self.matrixMultiply(x, x) + y >>= 1 + return r + + def numberOfWays(self, s: str, t: str, k: int) -> int: + n = len(s) + dp = self.matrixPower([[0, 1], [n - 1, n - 2]], k)[0] + s += t + t + z = self.getZ(s) + m = n + n + result = 0 + for i in range(n, m): + if z[i] >= n: + result = self.add(result, dp[0] if i - n == 0 else dp[1]) + return result \ No newline at end of file From ecfcfb467e8c2adcf43e5c57ee4c15d340997b9b Mon Sep 17 00:00:00 2001 From: Hiren Thakore Date: Mon, 25 Sep 2023 17:23:08 -0400 Subject: [PATCH 6/7] formatted cpp and java solutions with clang format tool --- .../2851.String Transformation/Solution.cpp | 101 +++++++++--------- .../2851.String Transformation/Solution.java | 2 +- 2 files changed, 51 insertions(+), 52 deletions(-) diff --git a/solution/2800-2899/2851.String Transformation/Solution.cpp b/solution/2800-2899/2851.String Transformation/Solution.cpp index fcf59f9fc0c5c..6996251d97b35 100644 --- a/solution/2800-2899/2851.String Transformation/Solution.cpp +++ b/solution/2800-2899/2851.String Transformation/Solution.cpp @@ -1,65 +1,64 @@ class Solution { -const int M = 1000000007; + const int M = 1000000007; -int add(int x, int y) { - if ((x += y) >= M) { - x -= M; + int add(int x, int y) { + if ((x += y) >= M) { + x -= M; + } + return x; } - return x; -} -int mul(long long x, long long y) { - return x * y % M; -} - - -vector getz(const string& s) { - const int n = s.length(); - vector z(n); - for (int i = 1, left = 0, right = 0; i < n; ++i) { - if (i <= right && z[i - left] <= right - i) { - z[i] = z[i - left]; - } else { - for (z[i] = max(0, right - i + 1); i + z[i] < n && s[i + z[i]] == s[z[i]]; ++z[i]) - ; - } - if (i + z[i] - 1 > right) { - left = i; - right = i + z[i] - 1; - } + int mul(long long x, long long y) { + return x * y % M; } - return z; -} - -vector> mul(const vector> &a, const vector> &b) { - const int m = a.size(), n = a[0].size(), p = b[0].size(); - vector> r(m, vector(p)); - for (int i = 0; i < m; ++i) { - for (int j = 0; j < n; ++j) { - for (int k = 0; k < p; ++k) { - r[i][k] = add(r[i][k], mul(a[i][j], b[j][k])); + + vector getz(const string& s) { + const int n = s.length(); + vector z(n); + for (int i = 1, left = 0, right = 0; i < n; ++i) { + if (i <= right && z[i - left] <= right - i) { + z[i] = z[i - left]; + } else { + for (z[i] = max(0, right - i + 1); i + z[i] < n && s[i + z[i]] == s[z[i]]; ++z[i]) + ; + } + if (i + z[i] - 1 > right) { + left = i; + right = i + z[i] - 1; } } + return z; } - return r; -} - -vector> pow(const vector> &a, long long y) { - const int n = a.size(); - vector> r(n, vector(n)); - for (int i = 0; i < n; ++i) { - r[i][i] = 1; + + vector> mul(const vector>& a, const vector>& b) { + const int m = a.size(), n = a[0].size(), p = b[0].size(); + vector> r(m, vector(p)); + for (int i = 0; i < m; ++i) { + for (int j = 0; j < n; ++j) { + for (int k = 0; k < p; ++k) { + r[i][k] = add(r[i][k], mul(a[i][j], b[j][k])); + } + } + } + return r; } - auto x = a; - for (; y; y >>= 1) { - if (y & 1) { - r = mul(r, x); + + vector> pow(const vector>& a, long long y) { + const int n = a.size(); + vector> r(n, vector(n)); + for (int i = 0; i < n; ++i) { + r[i][i] = 1; } - x = mul(x, x); + auto x = a; + for (; y; y >>= 1) { + if (y & 1) { + r = mul(r, x); + } + x = mul(x, x); + } + return r; } - return r; -} - + public: int numberOfWays(string s, string t, long long k) { const int n = s.length(); diff --git a/solution/2800-2899/2851.String Transformation/Solution.java b/solution/2800-2899/2851.String Transformation/Solution.java index 9139f8b0240c4..f90976310b381 100644 --- a/solution/2800-2899/2851.String Transformation/Solution.java +++ b/solution/2800-2899/2851.String Transformation/Solution.java @@ -68,7 +68,7 @@ private int[][] matrixPower(int[][] a, long y) { public int numberOfWays(String s, String t, long k) { int n = s.length(); - int[] dp = matrixPower(new int[][]{{0, 1}, {n - 1, n - 2}}, k)[0]; + int[] dp = matrixPower(new int[][] {{0, 1}, {n - 1, n - 2}}, k)[0]; s += t + t; int[] z = getZ(s); int m = n + n; From 0127b24ceb59c91cb0b776d3ab966a9ad264cffe Mon Sep 17 00:00:00 2001 From: Libin YANG Date: Tue, 26 Sep 2023 07:34:11 +0800 Subject: [PATCH 7/7] style: format python code with black --- .../2851.String Transformation/Solution.py | 23 +++---------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/solution/2800-2899/2851.String Transformation/Solution.py b/solution/2800-2899/2851.String Transformation/Solution.py index 878d8004772d9..bde0171b17856 100644 --- a/solution/2800-2899/2851.String Transformation/Solution.py +++ b/solution/2800-2899/2851.String Transformation/Solution.py @@ -1,54 +1,37 @@ -''' +""" DP, Z-algorithm, Fast mod. - Approach How to represent a string? Each operation is just a rotation. Each result string can be represented by an integer from 0 to n - 1. Namely, it's just the new index of s[0]. - How to find the integer(s) that can represent string t? Create a new string s + t + t (length = 3 * n). Use Z-algorithm (or KMP), for each n <= index < 2 * n, calculate the maximum prefix length that each substring starts from index can match, if the length >= n, then (index - n) is a valid integer representation. - How to get the result? It's a very obvious DP. If we use an integer to represent a string, we only need to consider the transition from zero to non-zero and from non-zero to zero. In other words, all the non-zero strings should have the same result. - So let dp[t][i = 0/1] be the number of ways to get the zero/nonzero string after excatly t steps. Then dp[t][0] = dp[t - 1][1] * (n - 1). All the non zero strings can make it. - dp[t][1] = dp[t - 1][0] + dp[t - 1] * (n - 2). For a particular non zero string, all the other non zero strings and zero string can make it. - We have dp[0][0] = 1 and dp[0][1] = 0 - Use matrix multiplication. How to calculate dp[k][x = 0, 1] faster? - Use matrix multiplication - vector (dp[t - 1][0], dp[t - 1][1]) - multiplies matrix - [0 1] [n - 1 n - 2] - == vector (dp[t][0], dp[t - 1][1]). - So we just need to calculate the kth power of the matrix which can be done by fast power algorith. - Complexity Time complexity: O(n + logk) - Space complexity: O(n) - -''' - +""" class Solution: @@ -114,4 +97,4 @@ def numberOfWays(self, s: str, t: str, k: int) -> int: for i in range(n, m): if z[i] >= n: result = self.add(result, dp[0] if i - n == 0 else dp[1]) - return result \ No newline at end of file + return result