Skip to content

Commit 6b8a81d

Browse files
authored
feat: add solutions to lc problem: No.2851 (doocs#1676)
No.2851.String Transformation
1 parent f82e843 commit 6b8a81d

File tree

3 files changed

+261
-0
lines changed

3 files changed

+261
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
class Solution {
2+
const int M = 1000000007;
3+
4+
int add(int x, int y) {
5+
if ((x += y) >= M) {
6+
x -= M;
7+
}
8+
return x;
9+
}
10+
11+
int mul(long long x, long long y) {
12+
return x * y % M;
13+
}
14+
15+
vector<int> getz(const string& s) {
16+
const int n = s.length();
17+
vector<int> z(n);
18+
for (int i = 1, left = 0, right = 0; i < n; ++i) {
19+
if (i <= right && z[i - left] <= right - i) {
20+
z[i] = z[i - left];
21+
} else {
22+
for (z[i] = max(0, right - i + 1); i + z[i] < n && s[i + z[i]] == s[z[i]]; ++z[i])
23+
;
24+
}
25+
if (i + z[i] - 1 > right) {
26+
left = i;
27+
right = i + z[i] - 1;
28+
}
29+
}
30+
return z;
31+
}
32+
33+
vector<vector<int>> mul(const vector<vector<int>>& a, const vector<vector<int>>& b) {
34+
const int m = a.size(), n = a[0].size(), p = b[0].size();
35+
vector<vector<int>> r(m, vector<int>(p));
36+
for (int i = 0; i < m; ++i) {
37+
for (int j = 0; j < n; ++j) {
38+
for (int k = 0; k < p; ++k) {
39+
r[i][k] = add(r[i][k], mul(a[i][j], b[j][k]));
40+
}
41+
}
42+
}
43+
return r;
44+
}
45+
46+
vector<vector<int>> pow(const vector<vector<int>>& a, long long y) {
47+
const int n = a.size();
48+
vector<vector<int>> r(n, vector<int>(n));
49+
for (int i = 0; i < n; ++i) {
50+
r[i][i] = 1;
51+
}
52+
auto x = a;
53+
for (; y; y >>= 1) {
54+
if (y & 1) {
55+
r = mul(r, x);
56+
}
57+
x = mul(x, x);
58+
}
59+
return r;
60+
}
61+
62+
public:
63+
int numberOfWays(string s, string t, long long k) {
64+
const int n = s.length();
65+
const auto dp = pow({{0, 1}, {n - 1, n - 2}}, k)[0];
66+
s.append(t);
67+
s.append(t);
68+
const auto z = getz(s);
69+
const int m = n + n;
70+
int r = 0;
71+
for (int i = n; i < m; ++i) {
72+
if (z[i] >= n) {
73+
r = add(r, dp[!!(i - n)]);
74+
}
75+
}
76+
return r;
77+
}
78+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
class Solution {
2+
private static final int M = 1000000007;
3+
4+
private int add(int x, int y) {
5+
if ((x += y) >= M) {
6+
x -= M;
7+
}
8+
return x;
9+
}
10+
11+
private int mul(long x, long y) {
12+
return (int) (x * y % M);
13+
}
14+
15+
private int[] getZ(String s) {
16+
int n = s.length();
17+
int[] z = new int[n];
18+
for (int i = 1, left = 0, right = 0; i < n; ++i) {
19+
if (i <= right && z[i - left] <= right - i) {
20+
z[i] = z[i - left];
21+
} else {
22+
int z_i = Math.max(0, right - i + 1);
23+
while (i + z_i < n && s.charAt(i + z_i) == s.charAt(z_i)) {
24+
z_i++;
25+
}
26+
z[i] = z_i;
27+
}
28+
if (i + z[i] - 1 > right) {
29+
left = i;
30+
right = i + z[i] - 1;
31+
}
32+
}
33+
return z;
34+
}
35+
36+
private int[][] matrixMultiply(int[][] a, int[][] b) {
37+
int m = a.length, n = a[0].length, p = b[0].length;
38+
int[][] r = new int[m][p];
39+
for (int i = 0; i < m; ++i) {
40+
for (int j = 0; j < p; ++j) {
41+
for (int k = 0; k < n; ++k) {
42+
r[i][j] = add(r[i][j], mul(a[i][k], b[k][j]));
43+
}
44+
}
45+
}
46+
return r;
47+
}
48+
49+
private int[][] matrixPower(int[][] a, long y) {
50+
int n = a.length;
51+
int[][] r = new int[n][n];
52+
for (int i = 0; i < n; ++i) {
53+
r[i][i] = 1;
54+
}
55+
int[][] x = new int[n][n];
56+
for (int i = 0; i < n; ++i) {
57+
System.arraycopy(a[i], 0, x[i], 0, n);
58+
}
59+
while (y > 0) {
60+
if ((y & 1) == 1) {
61+
r = matrixMultiply(r, x);
62+
}
63+
x = matrixMultiply(x, x);
64+
y >>= 1;
65+
}
66+
return r;
67+
}
68+
69+
public int numberOfWays(String s, String t, long k) {
70+
int n = s.length();
71+
int[] dp = matrixPower(new int[][] {{0, 1}, {n - 1, n - 2}}, k)[0];
72+
s += t + t;
73+
int[] z = getZ(s);
74+
int m = n + n;
75+
int result = 0;
76+
for (int i = n; i < m; ++i) {
77+
if (z[i] >= n) {
78+
result = add(result, dp[i - n == 0 ? 0 : 1]);
79+
}
80+
}
81+
return result;
82+
}
83+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
"""
2+
DP, Z-algorithm, Fast mod.
3+
Approach
4+
How to represent a string?
5+
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].
6+
How to find the integer(s) that can represent string t?
7+
Create a new string s + t + t (length = 3 * n).
8+
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.
9+
How to get the result?
10+
It's a very obvious DP.
11+
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.
12+
So let dp[t][i = 0/1] be the number of ways to get the zero/nonzero string
13+
after excatly t steps.
14+
Then
15+
dp[t][0] = dp[t - 1][1] * (n - 1).
16+
All the non zero strings can make it.
17+
dp[t][1] = dp[t - 1][0] + dp[t - 1] * (n - 2).
18+
For a particular non zero string, all the other non zero strings and zero string can make it.
19+
We have dp[0][0] = 1 and dp[0][1] = 0
20+
Use matrix multiplication.
21+
How to calculate dp[k][x = 0, 1] faster?
22+
Use matrix multiplication
23+
vector (dp[t - 1][0], dp[t - 1][1])
24+
multiplies matrix
25+
[0 1]
26+
[n - 1 n - 2]
27+
== vector (dp[t][0], dp[t - 1][1]).
28+
So we just need to calculate the kth power of the matrix which can be done by fast power algorith.
29+
Complexity
30+
Time complexity:
31+
O(n + logk)
32+
Space complexity:
33+
O(n)
34+
"""
35+
36+
37+
class Solution:
38+
M: int = 1000000007
39+
40+
def add(self, x: int, y: int) -> int:
41+
x += y
42+
if x >= self.M:
43+
x -= self.M
44+
return x
45+
46+
def mul(self, x: int, y: int) -> int:
47+
return int(x * y % self.M)
48+
49+
def getZ(self, s: str) -> List[int]:
50+
n = len(s)
51+
z = [0] * n
52+
left = right = 0
53+
for i in range(1, n):
54+
if i <= right and z[i - left] <= right - i:
55+
z[i] = z[i - left]
56+
else:
57+
z_i = max(0, right - i + 1)
58+
while i + z_i < n and s[i + z_i] == s[z_i]:
59+
z_i += 1
60+
z[i] = z_i
61+
if i + z[i] - 1 > right:
62+
left = i
63+
right = i + z[i] - 1
64+
return z
65+
66+
def matrixMultiply(self, a: List[List[int]], b: List[List[int]]) -> List[List[int]]:
67+
m = len(a)
68+
n = len(a[0])
69+
p = len(b[0])
70+
r = [[0] * p for _ in range(m)]
71+
for i in range(m):
72+
for j in range(p):
73+
for k in range(n):
74+
r[i][j] = self.add(r[i][j], self.mul(a[i][k], b[k][j]))
75+
return r
76+
77+
def matrixPower(self, a: List[List[int]], y: int) -> List[List[int]]:
78+
n = len(a)
79+
r = [[0] * n for _ in range(n)]
80+
for i in range(n):
81+
r[i][i] = 1
82+
x = [a[i][:] for i in range(n)]
83+
while y > 0:
84+
if y & 1:
85+
r = self.matrixMultiply(r, x)
86+
x = self.matrixMultiply(x, x)
87+
y >>= 1
88+
return r
89+
90+
def numberOfWays(self, s: str, t: str, k: int) -> int:
91+
n = len(s)
92+
dp = self.matrixPower([[0, 1], [n - 1, n - 2]], k)[0]
93+
s += t + t
94+
z = self.getZ(s)
95+
m = n + n
96+
result = 0
97+
for i in range(n, m):
98+
if z[i] >= n:
99+
result = self.add(result, dp[0] if i - n == 0 else dp[1])
100+
return result

0 commit comments

Comments
 (0)