Solving "string reduction" challenge
algorithm, dynamic-programming
Solution
What makes this tricky is that you need to treat this as 2 dynamic programming problems in a row.
- Build up a table of, by character you wind up with, by start position, all of the possible end positions that are a block that can be reduced to that character.
- The smallest length that the final `i` characters of the string can be reduced to. (The table that you built in step 1 can be used to recursively reduce this problem to already solved subproblems.)
The second provides your answer. It is much more straightforward if you have already solved the first.
Problem
I have seen various discussions and code attempts at solving the "String reduction" problem from interviewstreet.com, but none of them does it via dynamic programming. Listed under the Dynamic Programming section, the problem is described as follows: Given a string consisting of a,b and c's, we can perform the following operation: Take any two adjacent distinct characters and replace it with the third character. For example, if 'a' and 'c' are adjacent, they can replaced with 'b'. What is the smallest string which can result by applying this operation repeatedly? The problem can be solved using exhaustive brute-force search, effectively creating a tree of all possible substitutions: ``` // this is more or less pseudo code from my head int GetMinLength(string s) { // solve edge cases if (s.Length == 1) return 1; if (s.Length == 2) return ReduceIfPossible(s); // recursive brute force int min = s.Length; for (int i = 0; i<s.Length-1; i++) { if (s[i] != s[i+1]) { var next = GetMinLength( s.Substring(0, i) + Reduce(s[i], s[i + 1]) + s.Substring(i + 2) ); if (next < min) min = next; } } } ``` This obviously fails for larger `N` (`N <= 100`), so I am trying to break it into smaller subproblems, memoize them, and merge results. The problem is that I cannot determine the state which would have "optimal substructure", needed to apply dynamic programming (or in other words to "merge" results from sub-problems). Minimizing a part of the string doesn't guarantee that the final string will really be the smallest solution. What would be the subproblem "state" in this case, which could be merged towards the final solution?