Leetcode 3335. Total Characters in String After Transformations I
Table of Contents
Problem Informations
- Problem Index: 3335
- Problem Link: Total Characters in String After Transformations I
- Topics: Hash Table, Math, String, Dynamic Programming, Counting
Problem Description
You are given a string s
and an integer t
, representing the number of transformations to perform. In one transformation, every character in s
is replaced according to the following rules:
- If the character is
'z'
, replace it with the string"ab"
. - Otherwise, replace it with the next character in the alphabet. For example,
'a'
is replaced with'b'
,'b'
is replaced with'c'
, and so on.
Return the length of the resulting string after exactly t
transformations.
Since the answer may be very large, return it modulo $10^9 + 7$.
Example 1:
Input: s = "abcyy"
, t = 2
Output: 7
Explanation:
First Transformation (t = 1):
'a'
becomes'b'
'b'
becomes'c'
'c'
becomes'd'
'y'
becomes'z'
'y'
becomes'z'
- String after the first transformation:
"bcdzz"
Second Transformation (t = 2):
'b'
becomes'c'
'c'
becomes'd'
'd'
becomes'e'
'z'
becomes"ab"
'z'
becomes"ab"
- String after the second transformation:
"cdeabab"
Final Length of the string: The string is
"cdeabab"
, which has 7 characters.
Example 2:
Input: s = "azbk"
, t = 1
Output: 5
Explanation:
First Transformation (t = 1):
'a'
becomes'b'
'z'
becomes"ab"
'b'
becomes'c'
'k'
becomes'l'
- String after the first transformation:
"babcl"
Final Length of the string: The string is
"babcl"
, which has 5 characters.
Constraints:
- $1 \leq s.\text{length} \leq 10^5$
s
consists only of lowercase English letters.- $1 \leq t \leq 10^5$
Intuition
The problem revolves around performing a series of transformations on a string, with each character either being incremented to the next alphabetical character or replaced by a longer string in the case of ‘z’. The challenge lies in efficiently determining the length of the string after a potentially large number of transformations (up to $10^5$), as direct simulation would be computationally prohibitive due to the exponential growth of the string’s length.
The key observation that guides our approach is that for any character other than ‘z’, its transformation path is straightforward: it progresses from one character to the next. However, for ‘z’, it is replaced by two characters, ‘a’ and ‘b’, thereby causing an exponential increase in the total length. To efficiently compute the length after multiple transformations, we can leverage the properties of linear transformations and powers of matrices, which allow us to encode these character transformations in a matrix and compute their effect iteratively through matrix exponentiation.
Approach
To determine the length of the string after t
transformations, we employ a matrix exponentiation strategy that represents character transformations as linear transformations in a 26-dimensional space (corresponding to the 26 alphabetic characters).
Representation as Vectors and Matrices:
- We represent the initial string
s
using a 26-dimensional vectorcharacterCount
, where each element corresponds to the count of a particular character (‘a’ to ‘z’). - Define a 26x26 transformation matrix
M
that encodes the rules of transformation:- For characters ‘a’ to ‘y’, each transitions to the next character, hence the matrix
M
will haveM[i][i-1] = 1
. - For ‘z’, it transitions to both ‘a’ and ‘b’, captured by setting
M[0][25] = 1
andM[1][25] = 1
.
- For characters ‘a’ to ‘y’, each transitions to the next character, hence the matrix
- We represent the initial string
Matrix Exponentiation:
- Compute the matrix power
M^t
using fast matrix exponentiation. This efficiently calculates the effect of applying the transformation matrixt
times. - This approach leverages the properties of matrix multiplication to compute the result in logarithmic time relative to
t
.
- Compute the matrix power
Transformation Application:
- Multiply the initial
characterCount
vector by the matrixM^t
, resulting in a new vector that represents the transformed character counts. - Sum the elements of this resulting vector to get the total length of the string after
t
transformations.
- Multiply the initial
Modulo Operation:
- Since the potential length can be very large, all operations involving counts are performed modulo $10^9 + 7$ to prevent overflow and adhere to the problem constraints.
By utilizing matrix exponentiation, this approach efficiently computes the length of the string after a large number of transformations, within acceptable time complexity, specifically $O(T \log t)$, where $T$ is a constant due to the fixed alphabet size.
Code
C++
#include <array>
#include <string>
class Solution {
// Define the large prime modulus
static constexpr long long MOD = 1'000'000'007;
// Define a matrix type with fixed dimensions 26x26
using Mat = std::array<std::array<long long, 26>, 26>;
// Define a vector type with fixed dimension 26
using Vec = std::array<long long, 26>;
// Multiply two matrices A and B
static Mat multiplyMatrix(const Mat& A, const Mat& B) {
Mat C{};
for (int i = 0; i < 26; ++i) {
for (int k = 0; k < 26; ++k) {
if (A[i][k]) {
long long a_ik = A[i][k];
for (int j = 0; j < 26; ++j) {
C[i][j] += a_ik * B[k][j] % MOD;
if (C[i][j] >= MOD) C[i][j] -= MOD;
}
}
}
}
return C;
}
// Multiply a matrix A with a vector v
static Vec multiplyMatrixVector(const Mat& A, const Vec& v) {
Vec result{};
for (int i = 0; i < 26; ++i) {
long long sum = 0;
for (int j = 0; j < 26; ++j) {
sum += A[i][j] * v[j] % MOD;
if (sum >= MOD) sum -= MOD;
}
result[i] = sum;
}
return result;
}
// Compute the power of a matrix using fast exponentiation
static Mat matrixPower(Mat base, int exp) {
Mat result{}; // Initialize the identity matrix
for (int i = 0; i < 26; ++i) result[i][i] = 1;
while (exp) {
if (exp & 1) result = multiplyMatrix(result, base);
base = multiplyMatrix(base, base);
exp >>= 1;
}
return result;
}
public:
// Calculate the length of the string after t transformations
int lengthAfterTransformations(std::string s, int t) {
// Step 1: Convert the initial string into a 26-dimensional count vector
Vec characterCount{};
for (char c : s) characterCount[c - 'a']++;
// Step 2: Create a 26x26 transformation matrix M for one transformation
Mat M{}; // Initially all elements are zero
for (int i = 0; i < 25; ++i) // Transition from x to x+1
M[i + 1][i] = 1;
M[0][25] = 1; // Transition from 'z' to 'a'
M[1][25] = 1; // Transition from 'z' to 'b'
// Step 3: Compute the matrix M^t
Mat Mt = matrixPower(M, t);
// Step 4: Multiply the vector and matrix to get the final character counts
Vec finalCount = multiplyMatrixVector(Mt, characterCount);
long long finalLength = 0;
for (long long count : finalCount) {
finalLength += count;
if (finalLength >= MOD) finalLength -= MOD;
}
return static_cast<int>(finalLength);
}
};
Python
class Solution:
# Define the large prime modulus
MOD = 1_000_000_007
# Define a matrix type with fixed dimensions 26x26
Mat = list[list[int]]
# Define a vector type with fixed dimension 26
Vec = list[int]
# Multiply two matrices A and B
@staticmethod
def multiplyMatrix(A: 'Solution.Mat', B: 'Solution.Mat') -> 'Solution.Mat':
C = [[0] * 26 for _ in range(26)]
for i in range(26):
for k in range(26):
if A[i][k]:
a_ik = A[i][k]
for j in range(26):
C[i][j] += a_ik * B[k][j] % Solution.MOD
if C[i][j] >= Solution.MOD:
C[i][j] -= Solution.MOD
return C
# Multiply a matrix A with a vector v
@staticmethod
def multiplyMatrixVector(A: 'Solution.Mat', v: 'Solution.Vec') -> 'Solution.Vec':
result = [0] * 26
for i in range(26):
sum = 0
for j in range(26):
sum += A[i][j] * v[j] % Solution.MOD
if sum >= Solution.MOD:
sum -= Solution.MOD
result[i] = sum
return result
# Compute the power of a matrix using fast exponentiation
@staticmethod
def matrixPower(base: 'Solution.Mat', exp: int) -> 'Solution.Mat':
result = [[0] * 26 for _ in range(26)] # Initialize the identity matrix
for i in range(26):
result[i][i] = 1
while exp:
if exp & 1:
result = Solution.multiplyMatrix(result, base)
base = Solution.multiplyMatrix(base, base)
exp >>= 1
return result
# Calculate the length of the string after t transformations
def lengthAfterTransformations(self, s: str, t: int) -> int:
# Step 1: Convert the initial string into a 26-dimensional count vector
characterCount = [0] * 26
for c in s:
characterCount[ord(c) - ord('a')] += 1
# Step 2: Create a 26x26 transformation matrix M for one transformation
M = [[0] * 26 for _ in range(26)] # Initially all elements are zero
for i in range(25): # Transition from x to x+1
M[i + 1][i] = 1
M[0][25] = 1 # Transition from 'z' to 'a'
M[1][25] = 1 # Transition from 'z' to 'b'
# Step 3: Compute the matrix M^t
Mt = Solution.matrixPower(M, t)
# Step 4: Multiply the vector and matrix to get the final character counts
finalCount = Solution.multiplyMatrixVector(Mt, characterCount)
finalLength = 0
for count in finalCount:
finalLength += count
if finalLength >= Solution.MOD:
finalLength -= Solution.MOD
return finalLength
Complexity
Time complexity: $O(26^3 \cdot \log{t})$
The time complexity is dominated by the matrix exponentiation process, which involves matrix multiplication. Since the size of the matrix is fixed at $26 \times 26$, matrix multiplication has a constant complexity of $O(26^3)$. The matrix exponentiation is performed using fast exponentiation (or exponentiation by squaring), which takes $O(\log{t})$ steps. Therefore, the total time complexity is $O(26^3 \cdot \log{t})$, which is effectively a constant-time operation due to the fixed dimension of the matrix.
Space complexity: $O(1)$
The space complexity is $O(1)$ because the space used by the matrices and vectors does not increase with the input size or number of transformations, $t$. The matrix and vector dimensions are constant as they represent the fixed set of 26 alphabet characters, leading to constant space usage. Thus, the space complexity remains constant.
Disclaimer: All reference materials on this website are sourced from the internet and are intended for learning purposes only. If you believe any content infringes upon your rights, please contact me at csnote.cc@gmail.com, and I will remove the relevant content promptly.
Feedback Welcome: If you notice any errors or areas for improvement in the articles, I warmly welcome your feedback and corrections. Your input will help this blog provide better learning resources. This is an ongoing process of learning and improvement, and your suggestions are valuable to me. You can reach me at csnote.cc@gmail.com.