Skip to content

Commit b6b8817

Browse files
authored
feat: add solutions to lc problem: No.3337 (#4406)
No.3337.Total Characters in String After Transformations II
1 parent ab51502 commit b6b8817

File tree

5 files changed

+560
-2
lines changed

5 files changed

+560
-2
lines changed

solution/3300-3399/3337.Total Characters in String After Transformations II/README.md

+191-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,15 @@ tags:
123123

124124
<!-- solution:start -->
125125

126-
### 方法一
126+
### 方法一:矩阵快速幂加速递推
127+
128+
我们定义 $f[i][j]$ 表示经过 $i$ 次转换后,字母表中第 $j$ 个字母的个数。初始时 $f[0][j]$ 为字符串 $s$ 中字母表中第 $j$ 个字母的个数。
129+
130+
由于每一次转换后第 $j$ 个字母的个数,都跟下一次转换有关,转换的次数 $t$ 较大,我们可以使用矩阵快速幂,来加速整个递推过程。
131+
132+
注意,答案可能非常大,我们需要对 $10^9 + 7$ 取模。
133+
134+
时间复杂度 $O(n + \log t \times |\Sigma|^3)$,空间复杂度 $O(|\Sigma|^2)$。其中 $|\Sigma|$ 为字母表的大小。
127135

128136
<!-- tabs:start -->
129137

@@ -251,13 +259,195 @@ class Solution {
251259
#### C++
252260

253261
```cpp
262+
class Solution {
263+
public:
264+
static constexpr int MOD = 1e9 + 7;
265+
static constexpr int M = 26;
266+
267+
using Matrix = vector<vector<int>>;
268+
269+
Matrix matmul(const Matrix& a, const Matrix& b) {
270+
int n = a.size(), p = b.size(), q = b[0].size();
271+
Matrix res(n, vector<int>(q, 0));
272+
for (int i = 0; i < n; ++i) {
273+
for (int k = 0; k < p; ++k) {
274+
if (a[i][k]) {
275+
for (int j = 0; j < q; ++j) {
276+
res[i][j] = (res[i][j] + 1LL * a[i][k] * b[k][j] % MOD) % MOD;
277+
}
278+
}
279+
}
280+
}
281+
return res;
282+
}
283+
284+
Matrix matpow(Matrix mat, int power) {
285+
Matrix res(M, vector<int>(M, 0));
286+
for (int i = 0; i < M; ++i) res[i][i] = 1;
287+
while (power) {
288+
if (power % 2) res = matmul(res, mat);
289+
mat = matmul(mat, mat);
290+
power /= 2;
291+
}
292+
return res;
293+
}
294+
295+
int lengthAfterTransformations(string s, int t, vector<int>& nums) {
296+
vector<int> cnt(M, 0);
297+
for (char c : s) {
298+
cnt[c - 'a']++;
299+
}
300+
301+
Matrix matrix(M, vector<int>(M, 0));
302+
for (int i = 0; i < M; ++i) {
303+
for (int j = 1; j <= nums[i]; ++j) {
304+
matrix[i][(i + j) % M] = 1;
305+
}
306+
}
307+
308+
Matrix cntMat(1, vector<int>(M));
309+
for (int i = 0; i < M; ++i) cntMat[0][i] = cnt[i];
310+
311+
Matrix factor = matpow(matrix, t);
312+
Matrix result = matmul(cntMat, factor);
313+
314+
int ans = 0;
315+
for (int x : result[0]) {
316+
ans = (ans + x) % MOD;
317+
}
254318

319+
return ans;
320+
}
321+
};
255322
```
256323
257324
#### Go
258325
259326
```go
327+
func lengthAfterTransformations(s string, t int, nums []int) int {
328+
const MOD = 1e9 + 7
329+
const M = 26
330+
331+
cnt := make([]int, M)
332+
for _, c := range s {
333+
cnt[int(c-'a')]++
334+
}
335+
336+
matrix := make([][]int, M)
337+
for i := 0; i < M; i++ {
338+
matrix[i] = make([]int, M)
339+
for j := 1; j <= nums[i]; j++ {
340+
matrix[i][(i+j)%M] = 1
341+
}
342+
}
343+
344+
matmul := func(a, b [][]int) [][]int {
345+
n, p, q := len(a), len(b), len(b[0])
346+
res := make([][]int, n)
347+
for i := 0; i < n; i++ {
348+
res[i] = make([]int, q)
349+
for k := 0; k < p; k++ {
350+
if a[i][k] != 0 {
351+
for j := 0; j < q; j++ {
352+
res[i][j] = (res[i][j] + a[i][k]*b[k][j]%MOD) % MOD
353+
}
354+
}
355+
}
356+
}
357+
return res
358+
}
359+
360+
matpow := func(mat [][]int, power int) [][]int {
361+
res := make([][]int, M)
362+
for i := 0; i < M; i++ {
363+
res[i] = make([]int, M)
364+
res[i][i] = 1
365+
}
366+
for power > 0 {
367+
if power%2 == 1 {
368+
res = matmul(res, mat)
369+
}
370+
mat = matmul(mat, mat)
371+
power /= 2
372+
}
373+
return res
374+
}
375+
376+
cntMat := [][]int{make([]int, M)}
377+
copy(cntMat[0], cnt)
378+
379+
factor := matpow(matrix, t)
380+
result := matmul(cntMat, factor)
381+
382+
ans := 0
383+
for _, v := range result[0] {
384+
ans = (ans + v) % MOD
385+
}
386+
return ans
387+
}
388+
```
389+
390+
#### TypeScript
391+
392+
```ts
393+
function lengthAfterTransformations(s: string, t: number, nums: number[]): number {
394+
const MOD = BigInt(1e9 + 7);
395+
const M = 26;
260396

397+
const cnt: number[] = Array(M).fill(0);
398+
for (const c of s) {
399+
cnt[c.charCodeAt(0) - 'a'.charCodeAt(0)]++;
400+
}
401+
402+
const matrix: number[][] = Array.from({ length: M }, () => Array(M).fill(0));
403+
for (let i = 0; i < M; i++) {
404+
for (let j = 1; j <= nums[i]; j++) {
405+
matrix[i][(i + j) % M] = 1;
406+
}
407+
}
408+
409+
const matmul = (a: number[][], b: number[][]): number[][] => {
410+
const n = a.length,
411+
p = b.length,
412+
q = b[0].length;
413+
const res: number[][] = Array.from({ length: n }, () => Array(q).fill(0));
414+
for (let i = 0; i < n; i++) {
415+
for (let k = 0; k < p; k++) {
416+
const aik = BigInt(a[i][k]);
417+
if (aik !== BigInt(0)) {
418+
for (let j = 0; j < q; j++) {
419+
const product = aik * BigInt(b[k][j]);
420+
const sum = BigInt(res[i][j]) + product;
421+
res[i][j] = Number(sum % MOD);
422+
}
423+
}
424+
}
425+
}
426+
return res;
427+
};
428+
429+
const matpow = (mat: number[][], power: number): number[][] => {
430+
let res: number[][] = Array.from({ length: M }, (_, i) =>
431+
Array.from({ length: M }, (_, j) => (i === j ? 1 : 0)),
432+
);
433+
while (power > 0) {
434+
if (power % 2 === 1) res = matmul(res, mat);
435+
mat = matmul(mat, mat);
436+
power = Math.floor(power / 2);
437+
}
438+
return res;
439+
};
440+
441+
const cntMat: number[][] = [cnt.slice()];
442+
const factor = matpow(matrix, t);
443+
const result = matmul(cntMat, factor);
444+
445+
let ans = 0n;
446+
for (const v of result[0]) {
447+
ans = (ans + BigInt(v)) % MOD;
448+
}
449+
return Number(ans);
450+
}
261451
```
262452

263453
<!-- tabs:end -->

0 commit comments

Comments
 (0)