LeetCode 题解工作台
字符串转换
给你两个长度都为 n 的字符串 s 和 t 。你可以对字符串 s 执行以下操作: 将 s 长度为 l ( 0 )的 后缀字符串 删除,并将它添加在 s 的开头。 比方说, s = 'abcd' ,那么一次操作中,你可以删除后缀 'cd' ,并将它添加到 s 的开头,得到 s = 'cdab' 。 给…
4
题型
3
代码语言
3
相关题
当前训练重点
困难 · 状态·转移·动态规划
答案摘要
""" DP, Z-algorithm, Fast mod.
Interview AiBoxInterview AiBox 实时 AI 助手,陪你讲清 状态·转移·动态规划 题型思路
题目描述
给你两个长度都为 n 的字符串 s 和 t 。你可以对字符串 s 执行以下操作:
- 将
s长度为l(0 < l < n)的 后缀字符串 删除,并将它添加在s的开头。
比方说,s = 'abcd',那么一次操作中,你可以删除后缀'cd',并将它添加到s的开头,得到s = 'cdab'。
给你一个整数 k ,请你返回 恰好 k 次操作将 s 变为 t 的方案数。
由于答案可能很大,返回答案对 109 + 7 取余 后的结果。
示例 1:
输入:s = "abcd", t = "cdab", k = 2 输出:2 解释: 第一种方案: 第一次操作,选择 index = 3 开始的后缀,得到 s = "dabc" 。 第二次操作,选择 index = 3 开始的后缀,得到 s = "cdab" 。 第二种方案: 第一次操作,选择 index = 1 开始的后缀,得到 s = "bcda" 。 第二次操作,选择 index = 1 开始的后缀,得到 s = "cdab" 。
示例 2:
输入:s = "ababab", t = "ababab", k = 1 输出:2 解释: 第一种方案: 选择 index = 2 开始的后缀,得到 s = "ababab" 。 第二种方案: 选择 index = 4 开始的后缀,得到 s = "ababab" 。
提示:
2 <= s.length <= 5 * 1051 <= k <= 1015s.length == t.lengths和t都只包含小写英文字母。
解题思路
方法一
"""
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
复杂度分析
| 指标 | 值 |
|---|---|
| 时间 | Depends on the final approach |
| 空间 | Depends on the final approach |
面试官常问的追问
外企场景- question_mark
Candidate demonstrates understanding of state transition dynamic programming.
- question_mark
Candidate recognizes the importance of string rotations and modulo arithmetic in handling large numbers.
- question_mark
Candidate should explain how to optimize for large inputs and the trade-offs between time and space complexity.
常见陷阱
外企场景- error
Forgetting to handle the modulo operation, leading to overflow or incorrect answers.
- error
Misunderstanding the rotation property of string t and assuming it’s not derived from s.
- error
Overcomplicating the DP state transitions, missing out on optimizing the table for efficient solutions.
进阶变体
外企场景- arrow_right_alt
What if k is much smaller than the number of operations required? Consider edge cases where k is limited.
- arrow_right_alt
How would you approach this problem if we allowed substring rotations instead of suffix rotations?
- arrow_right_alt
What if we need to count the transformations modulo some different number instead of 10^9 + 7?