Haskell Largest String
import Data.Array (Array, bounds, elems, listArray, (!), (//))

largestString :: String -> String
largestString s0 = elems (go (len - 1) arr0 "")
  where
    len  = length s0
    arr0 = listArray (0, len - 1) s0 :: Array Int Char

    safeAt arr idx
      | idx >= 0 && idx <= snd (bounds arr) = Just (arr ! idx)
      | otherwise                           = Nothing

    go i arr cur
      | i < 0 = arr
      | otherwise =
          let cur1 = (arr ! i) : cur
          in  if length cur1 == 3
                then
                  let (arr1, i1) = handleTriplet i arr cur1
                      i2         = adjustEnd i1 arr1
                  in  go (i2 - 1) arr1 ""
                else go (i - 1) arr cur1

    handleTriplet i arr cur
      | cur == "abb" =
          let arr' = arr // [(i, 'b'), (i + 1, 'a'), (i + 2, 'a')]
          in  (arr', skipIndex i arr')
      | otherwise = (arr, i)

    skipIndex i arr
      | safeAt arr (i + 4) == Just 'b' = i + 4 + 1
      | safeAt arr (i + 3) == Just 'b' = i + 3 + 1
      | arr ! (i + 2) == 'b'           = i + 2 + 1
      | otherwise                      = i

    adjustEnd i arr
      | safeAt arr (i + 1) == Just 'b' = i + 1 + 1
      | otherwise                      = i + 1

This builds the biggest valid string it can under the challenge rules by always choosing the best next character it is allowed to use.