Created
May 14, 2025 16:30
-
-
Save tatsuyax25/d14705bca28069da9e051d3a251fb108 to your computer and use it in GitHub Desktop.
You are given a string s consisting of lowercase English letters, an integer t representing the number of transformations to perform, and an array nums of size 26. In one transformation, every character in s is replaced according to the following rul
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Computes the length of the transformed string after t transformations. | |
* @param {string} s - Input string consisting of lowercase English letters. | |
* @param {number} t - Number of transformations to apply. | |
* @param {number[]} nums - Array of size 26, mapping each letter to its transformation size. | |
* @returns {number} - Length of the resulting string modulo 10^9 + 7. | |
*/ | |
function lengthAfterTransformations(s, t, nums) { | |
const MOD = 1000000007n; // Large prime number for modulo operations | |
const bigT = BigInt(t); // Convert `t` to BigInt to handle large values | |
// Step 1: Count occurrences of each character in the input string | |
let count = Array(26).fill(0n); // Array to track letter frequencies | |
for (const ch of s) { | |
count[ch.charCodeAt(0) - 97]++; // Convert character to index ('a' = 0, ..., 'z' = 25) | |
} | |
// Step 2: Determine the number of bits needed to represent `t` | |
let bits = 0; | |
let tmp = bigT; | |
while (tmp > 0n) { | |
bits++; | |
tmp >>= 1n; // Bitwise right shift to count significant bits | |
} | |
if (bits === 0) bits = 1; // Ensure at least one transformation step | |
// Step 3: Create a transformation table (Sparse Power Table) | |
const spt = Array.from({ length: 26 }, () => | |
Array.from({ length: bits }, () => Array(26).fill(0n)) | |
); | |
// Step 4: Initialize transformation rules for first step | |
for (let i = 0; i < 26; i++) { | |
const maxStep = Math.min(26, nums[i]); // Limit step size to 26 (alphabet size) | |
for (let step = 1; step <= maxStep; step++) { | |
spt[i][0][(i + step) % 26]++; // Handle wrap-around transformation | |
} | |
} | |
// Step 5: Precompute transformation results for different bitwise steps | |
for (let b = 1; b < bits; b++) { | |
for (let i = 0; i < 26; i++) { | |
const out = spt[i][b]; // Transformation table for current bit | |
const prev = spt[i][b - 1]; // Previous bit transformations | |
for (let mid = 0; mid < 26; mid++) { | |
const ways1 = prev[mid]; // Ways to transform from previous step | |
if (ways1 === 0n) continue; | |
const row2 = spt[mid][b - 1]; // Second stage of transformation | |
for (let k = 0; k < 26; k++) { | |
out[k] = (out[k] + ways1 * row2[k]) % MOD; // Combine previous results | |
} | |
} | |
} | |
} | |
// Step 6: Apply transformations iteratively based on binary decomposition of `t` | |
let currCount = count; // Tracking current letter counts | |
for (let b = 0; b < bits; b++) { | |
if (((bigT >> BigInt(b)) & 1n) === 1n) { // Check if this bit is set in `t` | |
const next = Array(26).fill(0n); // New letter counts after transformation | |
for (let i = 0; i < 26; i++) { | |
const ci = currCount[i]; // Current character count | |
if (ci === 0n) continue; | |
const row = spt[i][b]; // Transformation rules for this step | |
for (let j = 0; j < 26; j++) { | |
next[j] = (next[j] + ci * row[j]) % MOD; // Update counts | |
} | |
} | |
currCount = next; // Update count for next iteration | |
} | |
} | |
// Step 7: Compute the final length after `t` transformations | |
let result = 0n; | |
for (const v of currCount) { | |
result = (result + v) % MOD; // Sum up final counts with modulo | |
} | |
return Number(result); // Convert BigInt back to regular number for output | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment