Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 6b8a81d

Browse files
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
Lines changed: 78 additions & 0 deletions
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+
};
Lines changed: 83 additions & 0 deletions
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+
}
Lines changed: 100 additions & 0 deletions
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)

AltStyle によって変換されたページ (->オリジナル) /