import Data.Coerce (coerce)
import Data.List (find, isPrefixOf)
import Data.Maybe (catMaybes)

newtype HoledChar = HC { unHC :: Char }

instance Eq HoledChar where
  HC '?' == _ = True
  _ == HC '?' = True
  HC a == HC b = a == b

instance Show HoledChar where
  show = show . unHC

eqHoles :: String -> String -> Bool
eqHoles as bs = and $ zipWith go as bs
  where
  go '?' _ = True
  go _ '?' = True
  go a b = a == b

type HoledString = [HoledChar]

mergePrefix :: HoledString -> HoledString -> [HoledString]
mergePrefix a b =
  map (\i -> take i a ++ merge (drop i a) b)
  $ filter (\i -> drop i a `isPrefixOf` b)
  $ [0..(length a - 1)]
  where
  merge (HC '?':xs) (y:ys) = y : merge xs ys
  merge (x:xs) (HC '?':ys) = x : merge xs ys
  merge (x:xs) (_:ys) = x : merge xs ys
  merge [] ys = ys
  merge _ _ = undefined

main :: IO ()
main = do
  a <- coerce getLine
  b <- coerce getLine
  c <- coerce getLine
  let abc = mergePrefix a b >>= flip mergePrefix c
      acb = mergePrefix a c >>= flip mergePrefix b
      bac = mergePrefix b a >>= flip mergePrefix c
      bca = mergePrefix b c >>= flip mergePrefix a
      cab = mergePrefix c a >>= flip mergePrefix b
      cba = mergePrefix c b >>= flip mergePrefix a
  print $ case map length $ concat [abc, acb, bac, bca, cab, cba] of
    [] -> -- no overlap, only simple concatenation is possible
      length a + length b + length c
    ls -> minimum ls
