You are given a string s and an integer k. A string can be partitioned such that each partition contains at most k distinct characters. You are allowed to change at most one character in s to any other lowercase English letter. Your goal is to maximize the number of valid partitions you can create after making this single optimal change.
This is an incredibly difficult problem (often considered one of the hardest string manipulation questions). It tests Dynamic Programming with Bitmasking under operation constraints. Interviewers ask it to evaluate if a candidate can abstract "distinct characters" into a bitmask and track complex states (whether a character has been changed yet) while simulating a greedy partitioning strategy.
This requires Top-Down DP with Memoization.
The state parameters are: (index, current_partition_bitmask, has_changed_char).
The current_partition_bitmask is an integer where the -th bit is 1 if the -th letter of the alphabet is in the current partition.
At each index, you have choices:
s[index] to the bitmask. If the bitmask now has bits, a new partition is forced (add 1 to score, reset bitmask).has_changed_char is false): Iterate through all 26 possible letters. Add the chosen letter to the bitmask, handle partition logic, and recurse with has_changed_char = true.
Memoize the max partitions returned.s = "accca", k = 2.
Without changing anything:
a: Mask {a}. Size 1.c: Mask {a, c}. Size 2.c: Mask {a, c}. Size 2.c: Mask {a, c}. Size 2.a: Mask {a, c}. Size 2.
Partitions = 1.What if we change the middle 'c' to 'b'? String becomes "acbca".
a: Mask {a}.c: Mask {a, c}. Size 2.b: Mask {a, c, b}. Size 3 ! Partition forced. New mask {b}. Partitions = 2.c: Mask {b, c}. Size 2.a: Mask {b, c, a}. Size 3 ! Partition forced. New mask {a}. Partitions = 3.
By optimally changing one character, we forced the greedy algorithm to break the string up more frequently. Max partitions = 3.The state space seems massive, causing candidates to panic. However, there are only 26 letters, so the bitmask is just an integer up to . A common mistake is using a Hash Set to track characters in the recursive function, which is too slow and can't be easily used as a cache key. Bitmasks are mandatory here. Another mistake is forgetting that adding a character that is already in the bitmask doesn't increase the unique count.
If you encounter this specific DP problem, explicitly mention the state reduction to the interviewer. Integer.bitCount(mask) instantly tells you how many distinct characters are in the current partition. By mapping the state to HashMap<String, Integer> (where the key is a string concatenation of index_mask_changed), you can tame the exponential search tree into a manageable DP solution.