3003. Maximize the Number of Partitions After Operations #2306
-
|
Topics: You are given a string First, you are allowed to change at most one index in After that, do the following partitioning operation until
Return an integer denoting the maximum number of resulting partitions after the operations by optimally choosing at most one index to change. Example 1:
Example 2:
Example 3:
Example 4:
Example 5:
Example 6:
Example 7:
Example 8:
Example 9:
Example 10:
Constraints:
Hint:
|
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
|
We need to determine the maximum number of partitions we can achieve by changing at most one character in the string and then partitioning the string greedily into segments where each segment contains at most Approach
Let's implement this solution in PHP: 3003. Maximize the Number of Partitions After Operations <?php
/**
* Main function to find maximum partitions
* @param String $s - input string
* @param Integer $k - max distinct characters per partition
* @return Integer - maximum number of partitions
*/
function maxPartitionsAfterOperations($s, $k) {
$n = strlen($s);
$memo = [];
// Start DFS from index 0, can change one char, empty mask
// Add 1 because we count partition boundaries, need to add final partition
$result = dfs(0, true, 0, $s, $k, $memo) + 1;
return $result;
}
/**
* DFS to explore all possibilities
* @param int $i - current index
* @param bool $canChange - can we still change a character?
* @param int $mask - bitmask of current partition's characters
* @return int - number of partition boundaries from this state
*/
function dfs($i, $canChange, $mask, $s, $k, &$memo) {
$n = strlen($s);
// Base case: reached end of string
if ($i === $n) {
return 0;
}
// Memoization key: combine all state variables
$key = $i . '|' . ($canChange ? '1' : '0') . '|' . $mask;
if (isset($memo[$key])) {
return $memo[$key];
}
$res = 0;
$currentChar = $s[$i];
// Convert character to bit position (a=0, b=1, ..., z=25)
$currentBit = 1 << (ord($currentChar) - ord('a'));
// **Option 1: Keep current character unchanged**
$newMask = $mask | $currentBit;
if (popcount($newMask) > $k) {
// Too many distinct chars - must start new partition
// Add 1 for partition boundary, continue with new partition
$res = max($res, 1 + dfs($i + 1, $canChange, $currentBit, $s, $k, $memo));
} else {
// Can continue current partition
$res = max($res, dfs($i + 1, $canChange, $newMask, $s, $k, $memo));
}
// **Option 2: Change current character (if allowed)**
if ($canChange) {
// Try all 26 possible characters
for ($c = 0; $c < 26; $c++) {
$newBit = 1 << $c;
// Skip if it's the same character
if ($newBit === $currentBit) continue;
$newMask = $mask | $newBit;
if (popcount($newMask) > $k) {
// New char causes overflow - start new partition
// Note: canChange becomes false after using it
$res = max($res, 1 + dfs($i + 1, false, $newBit, $s, $k, $memo));
} else {
// Can continue with changed character
$res = max($res, dfs($i + 1, false, $newMask, $s, $k, $memo));
}
}
}
// Store result in memo
$memo[$key] = $res;
return $res;
}
/**
* Count number of set bits in bitmask (distinct characters)
* @param int $x - bitmask
* @return int - count of 1 bits
*/
function popcount($x) {
$count = 0;
while ($x) {
$count += $x & 1; // Add 1 if last bit is set
$x >>= 1; // Right shift to check next bit
}
return $count;
}
// Test cases
$s1 = "accca"; $k1 = 2; // expected 3
$s2 = "aabaab"; $k2 = 3; // expected 1
$s3 = "xxyz"; $k3 = 1; // expected 4
echo maxPartitionsAfterOperations($s1, $k1) . PHP_EOL;
echo maxPartitionsAfterOperations($s2, $k2) . PHP_EOL;
echo maxPartitionsAfterOperations($s3, $k3) . PHP_EOL;
?>Explanation:Algorithm: DFS with MemoizationThe solution uses a depth-first search (DFS) approach with memoization to explore all possibilities: State Variables
Key Insight: Bitmask for Character TrackingInstead of storing a set of characters (inefficient), we use a 26-bit number: $currentBit = 1 << (ord($currentChar) - ord('a'));
// 'c' → ord('c')=99, ord('a')=97 → 99-97=2 → 1<<2 = 4 (binary: 100)Two Main Choices at Each PositionOption 1: Keep the Current Character$newMask = $mask | $currentBit; // Add current char to partition
if ($this->popcount($newMask) > $k) {
// Too many distinct characters - FORCE a partition boundary
$res = 1 + dfs(i+1, canChange, currentBit);
// Return 1 (for boundary) + remaining partitions starting fresh
} else {
// Can continue the current partition
$res = dfs(i+1, canChange, newMask);
}Logic: If adding the current character exceeds k distinct characters, we must end the current partition here and start a new one. Option 2: Change the Current Character (if allowed)if ($canChange) {
for ($c = 0; $c < 26; $c++) {
$newBit = 1 << $c;
if ($newBit === $currentBit) continue; // Skip unchanged character
$newMask = $mask | $newBit;
if ($this->popcount($newMask) > $k) {
$res = max($res, 1 + dfs(i+1, false, newBit));
} else {
$res = max($res, dfs(i+1, false, newMask));
}
}
}Logic: Try all 25 alternative characters. After using the change, set Memoization$key = $i . '|' . ($canChange ? '1' : '0') . '|' . $mask;Cache results for states we've already computed to avoid redundant calculations. Helper Function:
|
Beta Was this translation helpful? Give feedback.
We need to determine the maximum number of partitions we can achieve by changing at most one character in the string and then partitioning the string greedily into segments where each segment contains at most
kdistinct characters. The solution involves simulating the partitioning process for each possible character change and finding the maximum partitions among all scenarios.Approach
kdistinct characters.