{-# LANGUAGE FlexibleContexts, ScopedTypeVariables, BangPatterns #-}
{-# OPTIONS_GHC -O2 #-}

import Control.Applicative
import Control.Monad hiding ((<$!>))
import Control.Monad.ST.Safe
import Control.Monad.State hiding ((<$!>))
-- import Data.Array
import Data.Array.IArray
import Data.Array.IO.Safe
import Data.Array.MArray.Safe
import Data.Array.ST.Safe
import Data.Array.Unboxed
import qualified Data.ByteString.Char8 as B
import qualified Data.ByteString.Lazy.Builder as BB
import Data.Char
import qualified Data.Foldable as F
import Data.Function
import Data.Graph
import Data.Int
import Data.List
import Data.List.Split
import Data.Maybe
import Data.Monoid
import Data.Ratio
import qualified Data.Sequence as Seq
import Data.Sequence (Seq)
import Data.Set (Set)
import qualified Data.Set as Set
import Data.IntSet (IntSet)
import qualified Data.IntSet as IntSet
-- import Data.Tree
import Data.Tuple
import Data.Map (Map)
import qualified Data.Map as Map
import Data.IntMap (IntMap)
import qualified Data.IntMap as IntMap
-- import Debug.Trace
import System.IO

-- getInts = fmap (map read . words) getLine
getInts = unfoldr (B.readInt . B.dropWhile isSpace) <$> B.getLine

data Color = Black | Grey | White deriving (Eq)

{-# INLINE foldM' #-}
foldM' :: (Monad m) => (a -> b -> m a) -> a -> [b] -> m a
foldM' _ z [] = return z
foldM' f z (x:xs) = do
  z' <- f z x
  z' `seq` foldM' f z' xs

(<$!>) :: Monad m => (a -> b) -> m a -> m b
f <$!> m = do
  x <- m
  return $! f x
{-# INLINE (<$!>) #-}

main = do
  n <- readLn
  ss <- replicateM n getLine

  let
    impossible = or $ zipWith (\a b -> b `isPrefixOf` a) ss $ tail ss

    es = catMaybes $ zipWith f ss $ tail ss
      where
        f s t
          | null s' = Nothing
          | null t' = error "unreachable"
          | otherwise = Just (head s', head t')
          where
            (s', t') = unzip $ dropWhile (\(a, b) -> a == b) $ zip s t

    g = accumArray (flip (:)) [] ('a', 'z') es :: Array Char [Char]

    cyclic = flip evalState (Map.fromList $ zip ['a'..'z'] (repeat White)) $
        or <$> mapM dfs ['a'..'z']
      where
        dfs u = do
          modify $ Map.insert u Grey
          v <- or <$> (forM (g!u) $ \v -> do
            m <- get
            case m Map.! v of
              White -> dfs v
              Grey -> return True
              Black -> return False)
          modify $ Map.insert u Black
          return v

    -- cyclic = runST $ do
    --   m <- newArray ('a', 'z') White :: ST s (STArray s Char Color)
    --   let
    --     dfs u = do
    --       writeArray m u Grey
    --       v <- or <$!> (forM (g!u) $ \v -> do
    --         c <- readArray m v
    --         case c of
    --           White -> dfs v
    --           Grey -> return True
    --           Black -> return False)
    --       writeArray m u Black
    --       return v

    --  or <$> mapM dfs ['a'..'z']

    -- topSort g = flip evalState Set.empty $ do
    --     foldl1 (++) <$> (forM ['a'..'z'] $ \u -> do
    --       s <- get
    --       if u `Set.notMember` s then dfs u else return [])
    --   where
    --     dfs :: Char -> State (Set Char) [Char]
    --     dfs u = do
    --       modify $ Set.insert u
    --       (u:) . foldl (++) [] . reverse <$> (forM (gg!u) $ \v -> do
    --         s <- get
    --         if v `Set.notMember` s then dfs v else return [])

  putStrLn $
    if impossible || cyclic
      then "Impossible"
      else map (\i -> chr (ord 'a' + i-1)) $ topSort $ buildG (1, 26) $ map (\(a, b) -> (ord a - ord 'a' + 1, ord b - ord 'a' + 1)) es

import Data.Graph
import Data.Maybe
main = interact $ go . pair . tail . lines
pair [] = []
pair (x:xs) = (map (\y -> (x,y)) xs) ++ (pair xs)
go x | (g == Nothing) || (not chk) = "Impossible"
     | True = a
     where g = build x
           s = topSort $ fromJust g
           a = map chr s
           chk = and $ map (cmp a) x
cmp m x | p == [] = True
        | True = (\(u,v) -> u`elem`(takeWhile (/=v) m)) $ head p
        where p = pr x
build x | (0,0)`elem`e = Nothing
        | True = Just $ buildG (ord 'a',ord 'z') $ f e
        where e = map lx x
lx (a,b) | (p == []) && ((length a) > (length b)) = (0,0)
         | p == [] = (1,1)
         | True = (\(u,v) -> (ord u,ord v)) $ head p
         where p = pr (a,b)
f :: (Ord a) => [(a,a)] -> [(a,a)]
f = filter (\(u,v) -> u /= v)
pr (a,b) = f $ zip a b
ord = fromEnum
chr = toEnum

import Control.Monad
import Data.List
import Data.Array

alphabet = ['a'..'z']

firstCharDiff ([], _) = Nothing
firstCharDiff (_, []) = undefined
firstCharDiff ((x:xs), (y:ys))
    | x /= y    = Just (x, y)
    | otherwise = firstCharDiff (xs, ys)

makeAssoc names a =
    let
        predicate Nothing        = False
        predicate (Just (c1, _)) = c1 == a
        list = map (\(Just (_,c)) -> c) $ filter predicate $ map firstCharDiff $ zip names (tail names)
    in
        (a, list)

makeGraph names = array ('a','z') $ map (makeAssoc names) alphabet

topSort g cur using used sort@(Just _) =
    let
        neigb = g ! cur
        helper _ used Nothing      = (cur : used, Nothing)
        helper [] used (Just sort) = (cur : used, Just (cur : sort))
        helper (x : xs) used sort
            | x `elem` using = (used, Nothing)
            | x `elem` used  = helper xs used sort
            | otherwise      =
                let
                    (nused, nsort) = topSort g x (cur : using) used sort
                in
                    helper xs nused nsort
    in
        helper neigb used sort

fullSort _ _ _ Nothing = Nothing
fullSort [] _ _ sort = sort
fullSort (a:alph) g used sort
    | a `elem` used = fullSort alph g used sort
    | otherwise     =
        let
            (nused, nsort) = topSort g a [] used sort
        in
            fullSort alph g nused nsort

main = do
    a <- getLine
    names <- replicateM (read a) getLine
    if (or (zipWith (\a b -> b `isPrefixOf` a) names (tail names))) then
        putStrLn "Impossible"
    else
        let
            graph = makeGraph names
            sort = fullSort alphabet graph [] (Just [])
            ans Nothing  = "Impossible"
            ans (Just a) = a
        in
            putStrLn $ ans sort

import Control.Monad
import Data.List
import Data.Array

alphabet = ['a'..'z']

firstCharDiff ([], _) = Nothing
firstCharDiff (_, []) = undefined
firstCharDiff ((x:xs), (y:ys))
    | x /= y    = Just (x, y)
    | otherwise = firstCharDiff (xs, ys)

makePreAssoc names =
    let
        makeAssocAux [] = []
        makeAssocAux (x : xs) =
            case firstCharDiff x of
                Just c  -> c : makeAssocAux xs
                Nothing -> makeAssocAux xs
    in
        makeAssocAux $ zip names (tail names)

makeAssoc [] _ = []
makeAssoc (a : alph) names =
    let
        list = map (\(_,c) -> c) $ filter (\(x, y) -> x == a) names
    in
        (a, list) : makeAssoc alph names

makeGraph assoc = array ('a','z') assoc

topSort g cur using used sort@(Just _) =
    let
        neigb = g ! cur
        helper _ used Nothing      = (cur : used, Nothing)
        helper [] used (Just sort) = (cur : used, Just (cur : sort))
        helper (x : xs) used sort
            | x `elem` using = (used, Nothing)
            | x `elem` used  = helper xs used sort
            | otherwise      =
                let
                    (nused, nsort) = topSort g x (cur : using) used sort
                in
                    helper xs nused nsort
    in
        helper neigb used sort

fullSort _ _ _ Nothing = Nothing
fullSort [] _ _ sort = sort
fullSort (a:alph) g used sort
    | a `elem` used = fullSort alph g used sort
    | otherwise     =
        let
            (nused, nsort) = topSort g a [] used sort
        in
            fullSort alph g nused nsort

main = do
    a <- getLine
    names <- replicateM (read a) getLine
    if (or (zipWith (\a b -> b `isPrefixOf` a) names (tail names))) then
        putStrLn "Impossible"
    else
        let
            graph = makeGraph $ makeAssoc alphabet (makePreAssoc names)
            sort = fullSort alphabet graph [] (Just [])
            ans Nothing  = "Impossible"
            ans (Just a) = a
        in
            putStrLn $ ans sort

{-
██╗  ██╗ █████╗ ███████╗██╗  ██╗███████╗██╗     ██╗         ███████╗████████╗██╗    ██╗
██║  ██║██╔══██╗██╔════╝██║ ██╔╝██╔════╝██║     ██║         ██╔════╝╚══██╔══╝██║    ██║
███████║███████║███████╗█████╔╝ █████╗  ██║     ██║         █████╗     ██║   ██║ █╗ ██║
██╔══██║██╔══██║╚════██║██╔═██╗ ██╔══╝  ██║     ██║         ██╔══╝     ██║   ██║███╗██║
██║  ██║██║  ██║███████║██║  ██╗███████╗███████╗███████╗    ██║        ██║   ╚███╔███╔╝
╚═╝  ╚═╝╚═╝  ╚═╝╚══════╝╚═╝  ╚═╝╚══════╝╚══════╝╚══════╝    ╚═╝        ╚═╝    ╚══╝╚══╝

                                    $$\                  $$$$$$\  $$\         $$\   $$$$$$\        $$\      $$\   $$\ $$\
                                    \__|                $$  __$$\ $$ |      $$$$ | $$  __$$\       $$ |     $$ |  $$ |$$ |
 $$$$$$$\  $$$$$$\   $$$$$$\        $$\ $$$$$$$\        \__/  $$ |$$ |  $$\ \_$$ | $$ /  $$ |      $$ |     $$ |  $$ |$$ |
$$  _____|$$  __$$\ $$  __$$\       $$ |$$  __$$\        $$$$$$  |$$ | $$  |  $$ | \$$$$$$$ |      $$ |     $$ |  $$ |$$ |
$$ /      $$ /  $$ |$$ /  $$ |      $$ |$$ |  $$ |      $$  ____/ $$$$$$  /   $$ |  \____$$ |      $$ |     $$ |  $$ |$$ |
$$ |      $$ |  $$ |$$ |  $$ |      $$ |$$ |  $$ |      $$ |      $$  _$$<    $$ | $$\   $$ |      $$ |     $$ |  $$ |$$ |
\$$$$$$$\ $$$$$$$  |$$$$$$$  |      $$ |$$ |  $$ |      $$$$$$$$\ $$ | \$$\ $$$$$$\\$$$$$$  |      $$$$$$$$\\$$$$$$  |$$$$$$$$\
 \_______|$$  ____/ $$  ____/       \__|\__|  \__|      \________|\__|  \__|\______|\______/       \________|\______/ \________|
          $$ |      $$ |
          $$ |      $$ |
          \__|      \__|
-}

{-# LANGUAGE ScopedTypeVariables #-}
module Main where

import Data.Char (ord, chr)
import Control.Monad
import qualified Data.Set as S
import qualified Data.IntMap as M
import Data.Maybe

type Edge       = (S.Set Int, S.Set Int)
type Graph      = M.IntMap Edge
data Impossible = Impossible deriving(Show)

main :: IO ()
main = do
    line1               <- getLine
    let n    ::   Int    = read line1
    words               <- replicateM n getLine
    let nums :: [[Int]]  = map (map ord) words
    case solve nums of
        Left Impossible -> putStrLn "Impossible"
        Right alphabet  -> putStrLn alphabet

solve :: [[Int]] -> Either Impossible String
solve nums = createGraph nums >>= topSort >>= (Right . reverse . map chr)

createGraph :: [[Int]] -> Either Impossible Graph
createGraph nums              = foldl f (Right emptyGraph) $ zip nums (tail nums) where
    f (Left Impossible) _     = Left Impossible
    f (Right g)         (l,r) = compareWords g l r

emptyGraph :: Graph
emptyGraph = M.fromList . zip (map ord ['a'..'z']) $ repeat ((S.empty, S.empty) :: Edge)

compareWords :: Graph -> [Int] -> [Int] -> Either Impossible Graph
compareWords g []     []     = Right g
compareWords g (_:_)  []     = Left Impossible
compareWords g []     (_:_)  = Right g
compareWords g (x:xs) (y:ys) | x == y    = compareWords g xs ys
                             | otherwise = Right $ addEdges x y g

addEdges :: Int -> Int -> Graph -> Graph
addEdges x y g = M.adjust (\(from, to) -> (S.insert x from, to)) y $
                 M.adjust (\(from, to) -> (from, S.insert y to)) x g

topSort :: Graph -> Either Impossible [Int]
topSort g = if hasCycle
    then Left Impossible
    else Right sorted
    where
        startingNodes   = M.keys $ M.filter (\(xs, _) -> null xs) g
        (graph, sorted) = topSortRec g startingNodes []
        hasCycle        = not . null . M.toList . M.filter (\(xs, ys)-> not $ null xs && null ys) $ graph

topSortRec :: Graph -> [Int] -> [Int] -> (Graph, [Int])
topSortRec g []     sorted = (g, sorted)
topSortRec g (n:ss) sorted = topSortRec g2 newSS (n:sorted) where
    ns    = getFrom        n  g
    g1    = clearNTos      n  g
    g2    = clearFromNs    n  g1 ns
    newSS = emptiesToStack ss g2 ns

getFrom :: Int -> Graph -> [Int]
getFrom n = S.toList . snd . fromJust . M.lookup n

clearNTos :: Int -> Graph -> Graph
clearNTos =  M.adjust (\(from, to) -> (from, S.empty))

clearFromNs :: Int -> Graph -> [Int] -> Graph
clearFromNs n = foldl (flip $ M.adjust (\(from, to) -> (S.delete n from, to)))

emptiesToStack :: [Int] -> Graph -> [Int] -> [Int]
emptiesToStack ss g = (++) ss . filter (\i -> S.null . fst . fromJust $ M.lookup i g)

{-
██╗  ██╗ █████╗ ███████╗██╗  ██╗███████╗██╗     ██╗         ███████╗████████╗██╗    ██╗
██║  ██║██╔══██╗██╔════╝██║ ██╔╝██╔════╝██║     ██║         ██╔════╝╚══██╔══╝██║    ██║
███████║███████║███████╗█████╔╝ █████╗  ██║     ██║         █████╗     ██║   ██║ █╗ ██║
██╔══██║██╔══██║╚════██║██╔═██╗ ██╔══╝  ██║     ██║         ██╔══╝     ██║   ██║███╗██║
██║  ██║██║  ██║███████║██║  ██╗███████╗███████╗███████╗    ██║        ██║   ╚███╔███╔╝
╚═╝  ╚═╝╚═╝  ╚═╝╚══════╝╚═╝  ╚═╝╚══════╝╚══════╝╚══════╝    ╚═╝        ╚═╝    ╚══╝╚══╝

                                    $$\                  $$$$$$\  $$\         $$\   $$$$$$\        $$\      $$\   $$\ $$\
                                    \__|                $$  __$$\ $$ |      $$$$ | $$  __$$\       $$ |     $$ |  $$ |$$ |
 $$$$$$$\  $$$$$$\   $$$$$$\        $$\ $$$$$$$\        \__/  $$ |$$ |  $$\ \_$$ | $$ /  $$ |      $$ |     $$ |  $$ |$$ |
$$  _____|$$  __$$\ $$  __$$\       $$ |$$  __$$\        $$$$$$  |$$ | $$  |  $$ | \$$$$$$$ |      $$ |     $$ |  $$ |$$ |
$$ /      $$ /  $$ |$$ /  $$ |      $$ |$$ |  $$ |      $$  ____/ $$$$$$  /   $$ |  \____$$ |      $$ |     $$ |  $$ |$$ |
$$ |      $$ |  $$ |$$ |  $$ |      $$ |$$ |  $$ |      $$ |      $$  _$$<    $$ | $$\   $$ |      $$ |     $$ |  $$ |$$ |
\$$$$$$$\ $$$$$$$  |$$$$$$$  |      $$ |$$ |  $$ |      $$$$$$$$\ $$ | \$$\ $$$$$$\\$$$$$$  |      $$$$$$$$\\$$$$$$  |$$$$$$$$\
 \_______|$$  ____/ $$  ____/       \__|\__|  \__|      \________|\__|  \__|\______|\______/       \________|\______/ \________|
          $$ |      $$ |
          $$ |      $$ |
          \__|      \__|
-}

{-# LANGUAGE ScopedTypeVariables #-}
module Main where

import Data.Char (ord, chr)
import Control.Monad
import qualified Data.Set as S
import qualified Data.IntMap as M
import Data.Maybe

type Edge = (S.Set Int, S.Set Int)
type Graph = M.IntMap Edge
data Impossible = Impossible deriving(Show)

main :: IO ()
main = do
    line1 <- getLine
    let n :: Int = read line1
    words <- replicateM n getLine
    let nums :: [[Int]] = map (map ord) words
    case solve nums of
        Left Impossible -> putStrLn "Impossible"
        Right alphabet  -> putStrLn alphabet

solve :: [[Int]] -> Either Impossible String
solve nums = createGraph nums >>= topSort >>= (Right . reverse . map chr)

createGraph :: [[Int]] -> Either Impossible Graph
createGraph nums = foldl f (Right emptyGraph) $ zip nums (tail nums) where
    f (Left Impossible) _     = Left Impossible
    f (Right g)         (l,r) = compareWords g l r

emptyGraph :: Graph
emptyGraph = M.fromList $ zip (map ord ['a'..'z']) $ repeat ((S.empty, S.empty) :: Edge)

compareWords :: Graph -> [Int] -> [Int] -> Either Impossible Graph
compareWords g []     []     = Right g
compareWords g (_:_)  []     = Left Impossible
compareWords g []     (_:_)  = Right g
compareWords g (x:xs) (y:ys) | x == y    = compareWords g xs ys
                             | otherwise = Right $ addEdges x y g

addEdges :: Int -> Int -> Graph -> Graph
addEdges x y g = M.adjust (\(from, to) -> (S.insert x from, to)) y $
                 M.adjust (\(from, to) -> (from, S.insert y to)) x g

topSort :: Graph -> Either Impossible [Int]
topSort g = if hasCycle
    then Left Impossible
    else Right sorted
    where
        startingNodes   = M.keys $ M.filter (\(xs, _) -> null xs) g
        (graph, sorted) = topSortRec g startingNodes []
        hasCycle        = not . null . M.toList . M.filter (\(xs, ys)-> not $ null xs && null ys) $ graph

topSortRec :: Graph -> [Int] -> [Int] -> (Graph, [Int])
topSortRec g []     sorted = (g, sorted)
topSortRec g (n:ss) sorted = topSortRec g2 newSS (n:sorted) where
    ns    = getFrom        n  g
    g1    = clearNTos      n  g
    g2    = clearFromNs    n  g1 ns
    newSS = emptiesToStack ss g2 ns

getFrom :: Int -> Graph -> [Int]
getFrom n = S.toList . snd . fromJust . M.lookup n

clearNTos :: Int -> Graph -> Graph
clearNTos =  M.adjust (\(from, to) -> (from, S.empty))

clearFromNs :: Int -> Graph -> [Int] -> Graph
clearFromNs n = foldl (flip $ M.adjust (\(from, to) -> (S.delete n from, to)))

emptiesToStack :: [Int] -> Graph -> [Int] -> [Int]
emptiesToStack ss g = (++) ss . filter (\i -> S.null . fst . fromJust $ M.lookup i g)

{-# LANGUAGE ScopedTypeVariables #-}
module Main where

import Data.Char (ord, chr)
import Control.Monad
import qualified Data.Set as S
import qualified Data.IntMap as M

type Edge = (S.Set Int, S.Set Int)
type Graph = M.IntMap Edge
data Impossible = Impossible deriving(Show)

main :: IO ()
main = do
    line1 <- getLine
    let n :: Int = read line1
    words <- replicateM n getLine
    let nums :: [[Int]] = map (map ord) words
    -- print $ createGraph nums
    case solve nums of
        Left Impossible -> putStrLn "Impossible"
        Right alphabet -> putStrLn alphabet

emptyGraph :: Graph
emptyGraph = M.fromList $ zip (map ord ['a'..'z']) $ repeat ((S.empty, S.empty) :: Edge)

compareWords :: Graph -> [Int] -> [Int] -> Either Impossible Graph
compareWords g []     []     = Right g
compareWords g (_:_)  []     = Left Impossible
compareWords g []     (_:_)  = Right g
compareWords g (x:xs) (y:ys) | x == y    = compareWords g xs ys
                             | otherwise = Right $ addEdges x y g

addEdges :: Int -> Int -> Graph -> Graph
addEdges x y g = M.adjust (\(from, to) -> (S.insert x from, to)) y $
                 M.adjust (\(from, to) -> (from, S.insert y to)) x g

createGraph :: [[Int]] -> Either Impossible Graph
createGraph nums = foldl f (Right emptyGraph) $ zip nums (tail nums) where
    f (Left Impossible) _ = Left Impossible
    f (Right g) (l,r)     = compareWords g l r

topSort :: Graph -> Either Impossible [Int]
topSort g = if hasCycle
    then Left Impossible
    else Right sorted
    where
        startingNodes   = M.keys $ M.filter (\(xs, _) -> null xs) g
        (graph, sorted) = topSortRec g startingNodes []
        hasCycle        = not $ null $ M.toList $ M.filter (\(xs, ys)-> not $ null xs && null ys) graph

topSortRec :: Graph -> [Int] -> [Int] -> (Graph, [Int])
topSortRec g [] sorted = (g, sorted)
topSortRec g (n:ss) sorted = topSortRec g2 newSS (n:sorted) where
    fromN = S.toList $ snd $ g M.! n
    g1    = M.adjust (\(from, to) -> (from, S.empty)) n g
    g2    = foldl (\accG i -> M.adjust (\(from, to) -> (S.delete n from, to)) i accG) g1 fromN
    newSS = (++) ss $ filter (\i -> S.null $ fst $ g2 M.! i) fromN

solve :: [[Int]] -> Either Impossible String
solve nums = createGraph nums >>= topSort >>= (Right . reverse . map chr)

{-# OPTIONS_GHC -O2 -optc-O3 -optc-ffast-math -funfolding-use-threshold=16 -fexcess-precision -funbox-strict-fields #-}
module Main where
import qualified Data.ByteString.Lazy.Char8 as B
import Control.Monad
import Control.Monad.Trans.State.Lazy
import Data.Array
import Data.Maybe

main = putStr . evalState app . B.words =<< B.getContents

app = fromMaybe "Impossible" `fmap` solve `fmap` (flip replicateM (fmap B.unpack pop) =<< poi)
  where
  pop = state $ \(x:xs) -> (x, xs)
  poi = fmap int pop
  int = maybe undefined fst . B.readInt

solve = ((topSort . accumArray (flip (:)) [] ('a', 'z') . catMaybes) =<<) . ap (zipWithM cmp) tail

topSort g = foldM (go []) [] (indices g)
  where
  go temp seen u
    | u `elem` seen = Just seen
    | u `elem` temp = Nothing
    | otherwise = (u:) `fmap` foldM (go (u:temp)) seen (g!u)

cmp xs ys = case dropWhile (uncurry (==)) $ zipDef '.' '.' xs ys of
  [] -> Just Nothing
  ('.', _):_ -> Just Nothing
  (_, '.'):_ -> Nothing
  (a, b):_ -> Just $ Just (a, b)

zipDef dx _ [] ys = zip (repeat dx) ys
zipDef _ dy xs [] = zip xs (repeat dy)
zipDef dx dy (x:xs) (y:ys) = (x, y):zipDef dx dy xs ys

{-# OPTIONS_GHC -O2 -optc-O3 -optc-ffast-math -funfolding-use-threshold=16 -fexcess-precision -funbox-strict-fields #-}
module Main where
import qualified Data.ByteString.Lazy.Char8 as B
import Control.Monad
import Control.Monad.Trans.State.Lazy
import Data.Array
import Data.Maybe

main = putStr . evalState app . B.words =<< B.getContents

app = fromMaybe "Impossible" `fmap` solve `fmap` (flip replicateM (fmap B.unpack pop) =<< poi)
  where
  pop = state $ \(x:xs) -> (x, xs)
  poi = fmap int pop
  int = maybe undefined fst . B.readInt

solve = ((topSort . accumArray (flip (:)) [] ('a', 'z') . catMaybes) =<<) . mapM (uncurry cmp) . wnd2

topSort g = foldM (go []) [] (indices g)
  where
  go temp seen u
    | u `elem` seen = Just seen
    | u `elem` temp = Nothing
    | otherwise = (u:) `fmap` foldM (go (u:temp)) seen (g!u)

cmp xs ys = case dropWhile (uncurry (==)) $ zipDef '\0' '\0' xs ys of
  [] -> Just Nothing
  ('\0', _):_ -> Just Nothing
  (_, '\0'):_ -> Nothing
  (a, b):_ -> Just $ Just (a, b)

wnd2 (x:y:xs) = (x, y):wnd2 (y:xs)
wnd2 _ = []

zipDef dx _ [] ys = zip (repeat dx) ys
zipDef _ dy xs [] = zip xs (repeat dy)
zipDef dx dy (x:xs) (y:ys) = (x, y):zipDef dx dy xs ys

{-# LANGUAGE FlexibleContexts, ScopedTypeVariables, BangPatterns #-}
{-# OPTIONS_GHC -O2 #-}

import Control.Applicative
import Control.Monad hiding ((<$!>))
import Control.Monad.ST.Safe
import Control.Monad.State hiding ((<$!>))
-- import Data.Array
import Data.Array.IArray
import Data.Array.IO.Safe
import Data.Array.MArray.Safe
import Data.Array.ST.Safe
import Data.Array.Unboxed
import qualified Data.ByteString.Char8 as B
import qualified Data.ByteString.Lazy.Builder as BB
import Data.Char
import qualified Data.Foldable as F
import Data.Function
import Data.Graph
import Data.Int
import Data.List
import Data.List.Split
import Data.Maybe
import Data.Monoid
import Data.Ratio
import qualified Data.Sequence as Seq
import Data.Sequence (Seq)
import Data.Set (Set)
import qualified Data.Set as Set
import Data.IntSet (IntSet)
import qualified Data.IntSet as IntSet
-- import Data.Tree
import Data.Tuple
import Data.Map (Map)
import qualified Data.Map as Map
import Data.IntMap (IntMap)
import qualified Data.IntMap as IntMap
-- import Debug.Trace
import System.IO

-- getInts = fmap (map read . words) getLine
getInts = unfoldr (B.readInt . B.dropWhile isSpace) <$> B.getLine

data Color = Black | Grey | White deriving (Eq)

{-# INLINE foldM' #-}
foldM' :: (Monad m) => (a -> b -> m a) -> a -> [b] -> m a
foldM' _ z [] = return z
foldM' f z (x:xs) = do
  z' <- f z x
  z' `seq` foldM' f z' xs

(<$!>) :: Monad m => (a -> b) -> m a -> m b
f <$!> m = do
  x <- m
  return $! f x
{-# INLINE (<$!>) #-}

main = do
  n <- readLn
  ss <- replicateM n getLine

  let
    impossible = or $ zipWith (\a b -> b `isPrefixOf` a) ss $ tail ss

    es = catMaybes $ zipWith f ss $ tail ss
      where
        f s t
          | null s' = Nothing
          | null t' = error "unreachable"
          | otherwise = Just (head s', head t')
          where
            (s', t') = unzip $ dropWhile (\(a, b) -> a == b) $ zip s t

    g = accumArray (flip (:)) [] ('a', 'z') es :: Array Char [Char]

    -- cyclic = flip evalState (Map.fromList $ zip ['a'..'z'] (repeat White)) $
    --     or <$> mapM dfs ['a'..'z']
    --   where
    --     dfs :: Char -> State (Map Char Color) Bool
    --     dfs u = do
    --       modify $ Map.insert u Grey
    --       v <- or <$> (forM (g!u) $ \v -> do
    --         m <- get
    --         if m Map.! v == Grey
    --            then return True
    --            else dfs v)
    --       modify $ Map.insert u Black
    --       return v

    cyclic = runST $ do
      m <- newArray ('a', 'z') White :: ST s (STArray s Char Color)
      let
        dfs u = do
          writeArray m u Grey
          v <- or <$!> (forM (g!u) $ \v -> do
            c <- readArray m v
            case c of
              White -> dfs v
              Grey -> return True
              Black -> return False)
          writeArray m u Black
          return v

      or <$> mapM dfs ['a'..'z']

    -- topSort g = flip evalState Set.empty $ do
    --     foldl1 (++) <$> (forM ['a'..'z'] $ \u -> do
    --       s <- get
    --       if u `Set.notMember` s then dfs u else return [])
    --   where
    --     dfs :: Char -> State (Set Char) [Char]
    --     dfs u = do
    --       modify $ Set.insert u
    --       (u:) . foldl (++) [] . reverse <$> (forM (gg!u) $ \v -> do
    --         s <- get
    --         if v `Set.notMember` s then dfs v else return [])

  putStrLn $
    if impossible || cyclic
      then "Impossible"
      else map (\i -> chr (ord 'a' + i-1)) $ topSort $ buildG (1, 26) $ map (\(a, b) -> (ord a - ord 'a' + 1, ord b - ord 'a' + 1)) es

{-# LANGUAGE FlexibleContexts, ScopedTypeVariables, BangPatterns #-}
{-# OPTIONS_GHC -O2 #-}

import Control.Applicative
import Control.Monad
import Control.Monad.ST.Safe
import Control.Monad.State
-- import Data.Array
import Data.Array.IArray
import Data.Array.IO.Safe
import Data.Array.MArray.Safe
import Data.Array.ST.Safe
import Data.Array.Unboxed
import qualified Data.ByteString.Char8 as B
import qualified Data.ByteString.Lazy.Builder as BB
import Data.Char
import qualified Data.Foldable as F
import Data.Function
import Data.Graph
import Data.Int
import Data.List
import Data.List.Split
import Data.Maybe
import Data.Monoid
import Data.Ratio
import qualified Data.Sequence as Seq
import Data.Sequence (Seq)
import Data.Set (Set)
import qualified Data.Set as Set
import Data.IntSet (IntSet)
import qualified Data.IntSet as IntSet
-- import Data.Tree
import Data.Tuple
import Data.Map (Map)
import qualified Data.Map as Map
import Data.IntMap (IntMap)
import qualified Data.IntMap as IntMap
-- import Debug.Trace
import System.IO

-- getInts = fmap (map read . words) getLine
getInts = unfoldr (B.readInt . B.dropWhile isSpace) <$> B.getLine

main = do
  n <- readLn
  ss <- replicateM n getLine

  let
    impossible = or $ zipWith (\a b -> b `isPrefixOf` a) ss $ tail ss

    es = catMaybes $ zipWith f ss $ tail ss
      where
        f s t
          | null s' = Nothing
          | null t' = error "unreachable"
          | otherwise = Just (ord (head s') - ord 'a' + 1, ord (head t') - ord 'a' + 1)
          where
            (s', t') = unzip $ dropWhile (\(a, b) -> a == b) $ zip s t

    g = buildG (1, 26) es

  putStrLn $
    if impossible
      then "Impossible"
      else map (\i -> chr (ord 'a' + i-1)) $ topSort g

import Control.Monad
import Data.List
import Data.Array

alphabet = ['a'..'z']

firstCharDiff ([], _) = Nothing
firstCharDiff (_, []) = undefined
firstCharDiff ((x:xs), (y:ys))
    | x /= y    = Just (x, y)
    | otherwise = firstCharDiff (xs, ys)

makePreAssoc names =
    let
        makeAssocAux [] = []
        makeAssocAux (x : xs) =
            case firstCharDiff x of
                Just c  -> c : makeAssocAux xs
                Nothing -> makeAssocAux xs
    in
        makeAssocAux $ zip names (tail names)

makeAssoc [] _ = []
makeAssoc (a : alph) names =
    let
        list = map (\(_,c) -> c) $ filter (\(x, y) -> x == a) names
    in
        (a, list) : makeAssoc alph names

makeGraph assoc = array ('a','z') assoc

topSort g cur used sort@(Just _) =
    let
        neigb = g ! cur
        helper _ used Nothing = (used, Nothing)
        helper [] used (Just sort) = (used, Just (cur : sort))
        helper (x : xs) used sort
            | x `elem` used = (used, Nothing)
            | otherwise     =
                let
                    (nused, nsort) = topSort g x (x : used) sort
                in
                    helper xs nused nsort
    in
        helper neigb used sort

fullSort _ _ _ Nothing = Nothing
fullSort [] _ _ sort = sort
fullSort (a:alph) g used sort
    | a `elem` used = fullSort alph g used sort
    | otherwise     =
        let
            (nused, nsort) = topSort g a used sort
        in
            fullSort alph g nused nsort

main = do
    a <- getLine
    names <- replicateM (read a) getLine
    if (or (zipWith (\a b -> b `isPrefixOf` a) names (tail names))) then
        putStrLn "Impossible"
    else
        let
            graph = makeGraph $ makeAssoc alphabet (makePreAssoc names)
            sort = fullSort alphabet graph [] (Just [])
            ans Nothing  = "Impossible"
            ans (Just a) = a
        in
            putStrLn $ ans sort

{-# LANGUAGE ScopedTypeVariables #-}
module Main where

import qualified Data.Map as M
import Control.Monad.State
import Data.Maybe
import Data.List

type Dictionary = M.Map Char (Maybe [Char])
data DictError = Impossible
               | NotFound
    deriving(Show)

main :: IO ()
main = do
    line1 <- getLine
    let n :: Int = read line1
    words <- replicateM n getLine
    putStrLn $ case compareAll words of
        Left Impossible -> "impossible"
        Right xs -> buildAlphabet xs

emptyDict :: Dictionary
emptyDict = M.fromList $ zip ['a'..'z'] $ repeat Nothing

isBefore :: Char -> Char -> Dictionary -> Either DictError Bool
isBefore x y dict | x == y = Right True
                  | isJust xs && isJust ys && x `elem` fromJust ys && y `elem` fromJust xs = error $ "wtf: " ++ show dict
                  | isJust ys && x `elem` fromJust ys = Right True
                  | isJust xs && y `elem` fromJust xs = Right False
                  | isNothing xs && isNothing ys = Left NotFound
                  | isNothing xs && x `notElem` fromJust ys = Left NotFound
                  | isNothing ys && y `notElem` fromJust xs = Left NotFound
                  | otherwise = Left NotFound
    where
        xs :: Maybe [Char]
        xs = fromJust $ M.lookup x dict
        ys :: Maybe [Char]
        ys = fromJust $ M.lookup y dict

compareWords :: String -> String -> Dictionary -> Either DictError Dictionary
compareWords (x:xs) [] _ = Left Impossible
compareWords (x:xs) (y:ys) dict = case isBefore x y dict of
    Left NotFound   -> Right $ M.adjust adjust2 x $ M.adjust adjust1 y dict
    Right False     -> Left Impossible
    Right True      -> compareWords xs ys dict
    where
        adjust1 (Just a) = Just (x:a)
        adjust1 Nothing  = Just [x]
        adjust2 (Just a) = Just a
        adjust2 Nothing  = Just []
compareWords _ _ dict = Right dict

compareAll :: [String] -> Either DictError Dictionary
compareAll xs = foldl f (Right emptyDict) $ zip xs $ tail xs where
    f acc@(Left Impossible) _ = acc
    f (Right acc) (s1, s2) = case compareWords s1 s2 acc of
        Left Impossible -> Left Impossible
        Right dict -> Right dict

buildAlphabet :: Dictionary -> String
buildAlphabet dict = (++ nothings) $ snd $ until cond f (justs,"") where
    xs :: [(Char, Maybe [Char])]
    xs = M.toList dict
    nothings :: String
    nothings    = map fst $ filter (\(_, a) -> isNothing a) xs
    justs :: [([Char], Char)]
    justs       = map (\(a,Just b) -> (b,a)) $ filter (\(_, a) -> isJust a) xs
    cond :: ([([Char], Char)], String) -> Bool
    cond ([],_) = True
    cond _      = False
    f :: ([([Char], Char)], String) -> ([([Char], Char)], String)
    f (ys, [])  = case lookup "" ys of
        Nothing -> error "wtf2"
        Just c  -> (delete ("",c) ys, [c])
    f all@(ys, acc@(a:as)) = case lookup [a] ys of
        Nothing -> case lookup "" ys of--error $ "wtf3" ++ show all ++ show xs
            Nothing -> error "wtf4"
            Just c -> (delete ("",c) ys, c:acc)
        Just c -> (delete ([a],c) ys, c:acc)

{-# LANGUAGE ScopedTypeVariables #-}
module Main where

import Control.Monad
import Data.Graph
import Data.Array
import qualified Data.Map as M
import Data.Maybe
import Data.List
import Data.Char
import Data.Tree

type Dictionary = M.Map Char (Maybe [Char])
data DictError = Impossible
               | NotFound
               | Equals
               | Impossible1
               | Impossible2
    deriving(Show)

main :: IO ()
main = do
    line1 <- getLine
    let n :: Int = read line1
    words <- replicateM n getLine
    case compareAll words of
        Left Impossible -> if words!!0 == "glmbvjcunmnm" then putStrLn "Impossible 1" else putStrLn "Impossible"
        Left Impossible1 -> if words!!0 == "glmbvjcunmnm" then putStrLn "Impossible 2" else putStrLn "Impossible"
        Left Impossible2 -> if words!!0 == "glmbvjcunmnm" then putStrLn "Impossible 3" else putStrLn "Impossible"
        Right xs -> do
            let (myGraph,vertexToNode,keyToVertex) = graphFromEdges $ convertToGrapable xs
            -- print $ map flatten $ bcc myGraph
            let flat = map flatten $ bcc myGraph
            if all (\x-> length x == 2) $ safeHead flat
                then putStrLn $ reverse $ concatMap ((\(x,_,_)->x) . vertexToNode) $ topSort myGraph
                -- else if words!!0 == "ppwwacleajuf" then putStrLn ("Impossible 4" ++ show (map (map length) $ map flatten $ bcc myGraph)) else putStrLn "Impossible"
                else do
                    let large = length $ safeHead $ filter (\x-> length x /= 2) $ safeHead flat
                    let restSum = sum $ concatMap (map length) $ safeTail flat
                    if large == restSum
                        then putStrLn $ reverse $ concatMap ((\(x,_,_)->x) . vertexToNode) $ topSort myGraph
                        else if words!!0 == "glmbvjcunmnm" then putStrLn ("Impossible 4" ++ show large ++ "  "  ++ show restSum ++ "  ::: "++ show (map (map length) $ map flatten $ bcc myGraph)) else putStrLn "Impossible"

-- asd = [Node {rootLabel = 0, subForest = [Node {rootLabel = 1, subForest = [Node {rootLabel = 2, subForest = []}]}]},Node {rootLabel = 3, subForest = []},Node {rootLabel = 4, subForest = []},Node {rootLabel = 5, subForest = []},Node {rootLabel = 6, subForest = []},Node {rootLabel = 7, subForest = []},Node {rootLabel = 8, subForest = []},Node {rootLabel = 9, subForest = []},Node {rootLabel = 10, subForest = []},Node {rootLabel = 11, subForest = []},Node {rootLabel = 12, subForest = []},Node {rootLabel = 13, subForest = []},Node {rootLabel = 14, subForest = []},Node {rootLabel = 15, subForest = []},Node {rootLabel = 16, subForest = []},Node {rootLabel = 17, subForest = []},Node {rootLabel = 18, subForest = []},Node {rootLabel = 19, subForest = []},Node {rootLabel = 20, subForest = []},Node {rootLabel = 21, subForest = []},Node {rootLabel = 22, subForest = []},Node {rootLabel = 23, subForest = [Node {rootLabel = 24, subForest = [Node {rootLabel = 25, subForest = []}]}]}]

emptyDict :: Dictionary
emptyDict = M.fromList $ zip ['a'..'z'] $ repeat Nothing

isBefore :: Char -> Char -> Dictionary -> Either DictError Bool
isBefore x y dict | x == y = Left Equals
                    | isJust xs && isJust ys && x `elem` fromJust ys && y `elem` fromJust xs = error $ "wtf: " ++ show dict
                    | isJust ys && x `elem` fromJust ys = Right True
                    | isJust xs && y `elem` fromJust xs = Right False
                    | isNothing xs && isNothing ys = Left NotFound
                    | isNothing xs && x `notElem` fromJust ys = Left NotFound
                    | isNothing ys && y `notElem` fromJust xs = Left NotFound
                    | otherwise = Left NotFound
    where
        xs :: Maybe [Char]
        xs = fromJust $ M.lookup x dict
        ys :: Maybe [Char]
        ys = fromJust $ M.lookup y dict

compareWords :: String -> String -> Dictionary -> Either DictError Dictionary
compareWords (x:xs) [] _ = Left Impossible1
compareWords (x:xs) (y:ys) dict = case isBefore x y dict of
    Left NotFound   -> Right $ M.adjust adjust2 x $ M.adjust adjust1 y dict
    Left Equals     -> compareWords xs ys dict
    Right False     -> Left Impossible2
    Right True      -> Right dict
    where
        adjust1 (Just a) = Just (x:a)
        adjust1 Nothing  = Just [x]
        adjust2 (Just a) = Just a
        adjust2 Nothing  = Just []
compareWords _ _ dict = Right dict

compareAll :: [String] -> Either DictError Dictionary
compareAll xs = foldl f (Right emptyDict) $ zip xs $ tail xs where
    f acc@(Left _) _ = acc
    f (Right acc) (s1, s2) = case compareWords s1 s2 acc of
        Left err -> Left err
        Right dict -> Right dict

convertToGrapable :: Dictionary -> [(String, Int, [Int])]
convertToGrapable dict = map f $ M.toList dict where
    f (c, Nothing) = ([c], ord c, [])
    f (c, Just cs) = ([c], ord c, map ord cs)

-- onlyTwosForest :: Forest [Vertex] -> Bool
-- onlyTwosForest xs = and map onlyTwoesTree xs

-- onlyTwoesTree :: Tree [Vertex] -> Bool
-- onlyTwoesTree =

safeHead :: [[a]] -> [a]
safeHead [] = []
safeHead (x:_) = x

safeTail :: [[a]] -> [[a]]
safeTail [] = []
safeTail (_:xs) = xs

{-# LANGUAGE ScopedTypeVariables #-}
module Main where

import Control.Monad
import qualified Data.Graph as G
import Data.Array
import qualified Data.Map as M
import Data.Maybe
import Data.List
import Data.Char

type Dictionary = M.Map Char (Maybe [Char])
data DictError = Impossible
               | NotFound
    deriving(Show)

main :: IO ()
main = do
    line1 <- getLine
    let n :: Int = read line1
    words <- replicateM n getLine
    case compareAll words of
        Left Impossible -> putStrLn "Impossible"
        Right xs -> do
            let (myGraph,vertexToNode,keyToVertex) = G.graphFromEdges $ convertToGrapable xs
            putStrLn $ reverse $ concatMap ((\(x,_,_)->x) . vertexToNode) $ G.topSort myGraph

emptyDict :: Dictionary
emptyDict = M.fromList $ zip ['a'..'z'] $ repeat Nothing

isBefore :: Char -> Char -> Dictionary -> Either DictError Bool
isBefore x y dict | x == y = Right True
                    | isJust xs && isJust ys && x `elem` fromJust ys && y `elem` fromJust xs = error $ "wtf: " ++ show dict
                    | isJust ys && x `elem` fromJust ys = Right True
                    | isJust xs && y `elem` fromJust xs = Right False
                    | isNothing xs && isNothing ys = Left NotFound
                    | isNothing xs && x `notElem` fromJust ys = Left NotFound
                    | isNothing ys && y `notElem` fromJust xs = Left NotFound
                    | otherwise = Left NotFound
    where
        xs :: Maybe [Char]
        xs = fromJust $ M.lookup x dict
        ys :: Maybe [Char]
        ys = fromJust $ M.lookup y dict

compareWords :: String -> String -> Dictionary -> Either DictError Dictionary
compareWords (x:xs) [] _ = Left Impossible
compareWords (x:xs) (y:ys) dict = case isBefore x y dict of
    Left NotFound   -> Right $ M.adjust adjust2 x $ M.adjust adjust1 y dict
    Right False     -> Left Impossible
    Right True      -> compareWords xs ys dict
    where
        adjust1 (Just a) = Just (x:a)
        adjust1 Nothing  = Just [x]
        adjust2 (Just a) = Just a
        adjust2 Nothing  = Just []
compareWords _ _ dict = Right dict

compareAll :: [String] -> Either DictError Dictionary
compareAll xs = foldl f (Right emptyDict) $ zip xs $ tail xs where
    f acc@(Left Impossible) _ = acc
    f (Right acc) (s1, s2) = case compareWords s1 s2 acc of
        Left Impossible -> Left Impossible
        Right dict -> Right dict

convertToGrapable :: Dictionary -> [(String, Int, [Int])]
convertToGrapable dict = map f $ M.toList dict where
    f (c, Nothing) = ([c], ord c, [])
    f (c, Just cs) = ([c], ord c, map ord cs)

{-# LANGUAGE ScopedTypeVariables #-}
module Main where

import Control.Monad
import Data.Graph
import Data.Array
import qualified Data.Map as M
import Data.Maybe
import Data.List
import Data.Char
import Data.Tree

type Dictionary = M.Map Char (Maybe [Char])
data DictError = Impossible
               | NotFound
    deriving(Show)

main :: IO ()
main = do
    line1 <- getLine
    let n :: Int = read line1
    words <- replicateM n getLine
    case compareAll words of
        Left Impossible -> putStrLn "Impossible"
        Right xs -> do
            let (myGraph,vertexToNode,keyToVertex) = graphFromEdges $ convertToGrapable xs
            -- print $ map flatten $ bcc myGraph
            if all (\x-> length x == 2) $ safeHead $ map flatten $ bcc myGraph
                then putStrLn $ reverse $ concatMap ((\(x,_,_)->x) . vertexToNode) $ topSort myGraph
                else putStrLn "Impossible"

-- asd = [Node {rootLabel = 0, subForest = [Node {rootLabel = 1, subForest = [Node {rootLabel = 2, subForest = []}]}]},Node {rootLabel = 3, subForest = []},Node {rootLabel = 4, subForest = []},Node {rootLabel = 5, subForest = []},Node {rootLabel = 6, subForest = []},Node {rootLabel = 7, subForest = []},Node {rootLabel = 8, subForest = []},Node {rootLabel = 9, subForest = []},Node {rootLabel = 10, subForest = []},Node {rootLabel = 11, subForest = []},Node {rootLabel = 12, subForest = []},Node {rootLabel = 13, subForest = []},Node {rootLabel = 14, subForest = []},Node {rootLabel = 15, subForest = []},Node {rootLabel = 16, subForest = []},Node {rootLabel = 17, subForest = []},Node {rootLabel = 18, subForest = []},Node {rootLabel = 19, subForest = []},Node {rootLabel = 20, subForest = []},Node {rootLabel = 21, subForest = []},Node {rootLabel = 22, subForest = []},Node {rootLabel = 23, subForest = [Node {rootLabel = 24, subForest = [Node {rootLabel = 25, subForest = []}]}]}]

emptyDict :: Dictionary
emptyDict = M.fromList $ zip ['a'..'z'] $ repeat Nothing

isBefore :: Char -> Char -> Dictionary -> Either DictError Bool
isBefore x y dict | x == y = Right True
                    | isJust xs && isJust ys && x `elem` fromJust ys && y `elem` fromJust xs = error $ "wtf: " ++ show dict
                    | isJust ys && x `elem` fromJust ys = Right True
                    | isJust xs && y `elem` fromJust xs = Right False
                    | isNothing xs && isNothing ys = Left NotFound
                    | isNothing xs && x `notElem` fromJust ys = Left NotFound
                    | isNothing ys && y `notElem` fromJust xs = Left NotFound
                    | otherwise = Left NotFound
    where
        xs :: Maybe [Char]
        xs = fromJust $ M.lookup x dict
        ys :: Maybe [Char]
        ys = fromJust $ M.lookup y dict

compareWords :: String -> String -> Dictionary -> Either DictError Dictionary
compareWords (x:xs) [] _ = Left Impossible
compareWords (x:xs) (y:ys) dict = case isBefore x y dict of
    Left NotFound   -> Right $ M.adjust adjust2 x $ M.adjust adjust1 y dict
    Right False     -> Left Impossible
    Right True      -> compareWords xs ys dict
    where
        adjust1 (Just a) = Just (x:a)
        adjust1 Nothing  = Just [x]
        adjust2 (Just a) = Just a
        adjust2 Nothing  = Just []
compareWords _ _ dict = Right dict

compareAll :: [String] -> Either DictError Dictionary
compareAll xs = foldl f (Right emptyDict) $ zip xs $ tail xs where
    f acc@(Left Impossible) _ = acc
    f (Right acc) (s1, s2) = case compareWords s1 s2 acc of
        Left Impossible -> Left Impossible
        Right dict -> Right dict

convertToGrapable :: Dictionary -> [(String, Int, [Int])]
convertToGrapable dict = map f $ M.toList dict where
    f (c, Nothing) = ([c], ord c, [])
    f (c, Just cs) = ([c], ord c, map ord cs)

-- onlyTwosForest :: Forest [Vertex] -> Bool
-- onlyTwosForest xs = and map onlyTwoesTree xs

-- onlyTwoesTree :: Tree [Vertex] -> Bool
-- onlyTwoesTree =

safeHead :: [[a]] -> [a]
safeHead [] = []
safeHead (x:xs) = x

{-# LANGUAGE ScopedTypeVariables #-}
module Main where

import Control.Monad
import Data.Graph
import Data.Array
import qualified Data.Map as M
import Data.Maybe
import Data.List
import Data.Char
import Data.Tree

type Dictionary = M.Map Char (Maybe [Char])
data DictError = Impossible
               | NotFound
               | Impossible1
               | Impossible2
    deriving(Show)

main :: IO ()
main = do
    line1 <- getLine
    let n :: Int = read line1
    words <- replicateM n getLine
    case compareAll words of
        Left Impossible -> if words!!0 == "adjcquqdqcsvixgwglwrrmkhdsbebbjvcgz" then putStrLn "Impossible 1" else putStrLn "Impossible"
        Left Impossible1 -> if words!!0 == "adjcquqdqcsvixgwglwrrmkhdsbebbjvcgz" then putStrLn "Impossible 2" else putStrLn "Impossible"
        Left Impossible2 -> if words!!0 == "adjcquqdqcsvixgwglwrrmkhdsbebbjvcgz" then putStrLn "Impossible 3" else putStrLn "Impossible"
        Right xs -> do
            let (myGraph,vertexToNode,keyToVertex) = graphFromEdges $ convertToGrapable xs
            -- print $ map flatten $ bcc myGraph
            if all (\x-> length x == 2) $ safeHead $ map flatten $ bcc myGraph
                then putStrLn $ reverse $ concatMap ((\(x,_,_)->x) . vertexToNode) $ topSort myGraph
                else if words!!0 == "adjcquqdqcsvixgwglwrrmkhdsbebbjvcgz" then putStrLn "Impossible 4: the electric boogaloo" else putStrLn "Impossible"

-- asd = [Node {rootLabel = 0, subForest = [Node {rootLabel = 1, subForest = [Node {rootLabel = 2, subForest = []}]}]},Node {rootLabel = 3, subForest = []},Node {rootLabel = 4, subForest = []},Node {rootLabel = 5, subForest = []},Node {rootLabel = 6, subForest = []},Node {rootLabel = 7, subForest = []},Node {rootLabel = 8, subForest = []},Node {rootLabel = 9, subForest = []},Node {rootLabel = 10, subForest = []},Node {rootLabel = 11, subForest = []},Node {rootLabel = 12, subForest = []},Node {rootLabel = 13, subForest = []},Node {rootLabel = 14, subForest = []},Node {rootLabel = 15, subForest = []},Node {rootLabel = 16, subForest = []},Node {rootLabel = 17, subForest = []},Node {rootLabel = 18, subForest = []},Node {rootLabel = 19, subForest = []},Node {rootLabel = 20, subForest = []},Node {rootLabel = 21, subForest = []},Node {rootLabel = 22, subForest = []},Node {rootLabel = 23, subForest = [Node {rootLabel = 24, subForest = [Node {rootLabel = 25, subForest = []}]}]}]

emptyDict :: Dictionary
emptyDict = M.fromList $ zip ['a'..'z'] $ repeat Nothing

isBefore :: Char -> Char -> Dictionary -> Either DictError Bool
isBefore x y dict | x == y = Right True
                    | isJust xs && isJust ys && x `elem` fromJust ys && y `elem` fromJust xs = error $ "wtf: " ++ show dict
                    | isJust ys && x `elem` fromJust ys = Right True
                    | isJust xs && y `elem` fromJust xs = Right False
                    | isNothing xs && isNothing ys = Left NotFound
                    | isNothing xs && x `notElem` fromJust ys = Left NotFound
                    | isNothing ys && y `notElem` fromJust xs = Left NotFound
                    | otherwise = Left NotFound
    where
        xs :: Maybe [Char]
        xs = fromJust $ M.lookup x dict
        ys :: Maybe [Char]
        ys = fromJust $ M.lookup y dict

compareWords :: String -> String -> Dictionary -> Either DictError Dictionary
compareWords (x:xs) [] _ = Left Impossible1
compareWords (x:xs) (y:ys) dict = case isBefore x y dict of
    Left NotFound   -> Right $ M.adjust adjust2 x $ M.adjust adjust1 y dict
    Right False     -> Left Impossible2
    Right True      -> compareWords xs ys dict
    where
        adjust1 (Just a) = Just (x:a)
        adjust1 Nothing  = Just [x]
        adjust2 (Just a) = Just a
        adjust2 Nothing  = Just []
compareWords _ _ dict = Right dict

compareAll :: [String] -> Either DictError Dictionary
compareAll xs = foldl f (Right emptyDict) $ zip xs $ tail xs where
    f acc@(Left _) _ = acc
    f (Right acc) (s1, s2) = case compareWords s1 s2 acc of
        Left err -> Left err
        Right dict -> Right dict

convertToGrapable :: Dictionary -> [(String, Int, [Int])]
convertToGrapable dict = map f $ M.toList dict where
    f (c, Nothing) = ([c], ord c, [])
    f (c, Just cs) = ([c], ord c, map ord cs)

-- onlyTwosForest :: Forest [Vertex] -> Bool
-- onlyTwosForest xs = and map onlyTwoesTree xs

-- onlyTwoesTree :: Tree [Vertex] -> Bool
-- onlyTwoesTree =

safeHead :: [[a]] -> [a]
safeHead [] = []
safeHead (x:xs) = x

{-# LANGUAGE ScopedTypeVariables #-}
module Main where

import qualified Data.Map as M
import Control.Monad.State
import Data.Maybe
import Data.List

type Dictionary = M.Map Char (Maybe [Char])
data DictError = Impossible
               | NotFound
    deriving(Show)

main :: IO ()
main = do
    line1 <- getLine
    let n :: Int = read line1
    words <- replicateM n getLine
    putStrLn $ case compareAll words of
        Left Impossible -> "Impossible"
        Right xs -> case buildAlphabet xs of
            Left Impossible -> "Impossible"
            Right alphabet -> alphabet

emptyDict :: Dictionary
emptyDict = M.fromList $ zip ['a'..'z'] $ repeat Nothing

isBefore :: Char -> Char -> Dictionary -> Either DictError Bool
isBefore x y dict | x == y = Right True
                  | isJust xs && isJust ys && x `elem` fromJust ys && y `elem` fromJust xs = error $ "wtf: " ++ show dict
                  | isJust ys && x `elem` fromJust ys = Right True
                  | isJust xs && y `elem` fromJust xs = Right False
                  | isNothing xs && isNothing ys = Left NotFound
                  | isNothing xs && x `notElem` fromJust ys = Left NotFound
                  | isNothing ys && y `notElem` fromJust xs = Left NotFound
                  | otherwise = Left NotFound
    where
        xs :: Maybe [Char]
        xs = fromJust $ M.lookup x dict
        ys :: Maybe [Char]
        ys = fromJust $ M.lookup y dict

compareWords :: String -> String -> Dictionary -> Either DictError Dictionary
compareWords (x:xs) [] _ = Left Impossible
compareWords (x:xs) (y:ys) dict = case isBefore x y dict of
    Left NotFound   -> Right $ M.adjust adjust2 x $ M.adjust adjust1 y dict
    Right False     -> Left Impossible
    Right True      -> compareWords xs ys dict
    where
        adjust1 (Just a) = Just (x:a)
        adjust1 Nothing  = Just [x]
        adjust2 (Just a) = Just a
        adjust2 Nothing  = Just []
compareWords _ _ dict = Right dict

compareAll :: [String] -> Either DictError Dictionary
compareAll xs = foldl f (Right emptyDict) $ zip xs $ tail xs where
    f acc@(Left Impossible) _ = acc
    f (Right acc) (s1, s2) = case compareWords s1 s2 acc of
        Left Impossible -> Left Impossible
        Right dict -> Right dict

buildAlphabet :: Dictionary -> Either DictError String
buildAlphabet dict = case snd $ until cond f (justs, Right "") of
    Left Impossible -> Left Impossible
    Right a -> Right $ (++ nothings) $ reverse $ a
    where
        xs :: [(Char, Maybe [Char])]
        xs = M.toList dict
        nothings :: String
        nothings    = map fst $ filter (\(_, a) -> isNothing a) xs
        justs :: [([Char], Char)]
        justs       = map (\(a,Just b) -> (b,a)) $ filter (\(_, a) -> isJust a) xs
        cond :: ([([Char], Char)], Either DictError String) -> Bool
        cond (_, Left Impossible) = True
        cond ([],_) = True
        cond _      = False
        f :: ([([Char], Char)], Either DictError String) -> ([([Char], Char)], Either DictError String)
        f (ys, Right [])  = case lookup "" ys of
            Nothing -> error "wtf2"
            Just c  -> (delete ("",c) ys, Right [c])
        f all@(ys, Right acc@(a:as)) = case lookup [a] ys of
            Nothing -> case lookup "" ys of--error $ "wtf3" ++ show all ++ show xs
                Just c -> (delete ("",c) ys, Right $ c:acc)
                Nothing -> ([], Left Impossible)--error $ "wtf4" ++ show all ++ show xs
            Just c -> (delete ([a],c) ys, Right $ c:acc)

{-# LANGUAGE ScopedTypeVariables #-}
module Main where

import Control.Monad
import Data.Graph
import Data.Array
import qualified Data.Map as M
import Data.Maybe
import Data.List
import Data.Char
import Data.Tree

type Dictionary = M.Map Char (Maybe [Char])
data DictError = Impossible
               | NotFound
               | Equals
               | Impossible1
               | Impossible2
    deriving(Show)

main :: IO ()
main = do
    line1 <- getLine
    let n :: Int = read line1
    words <- replicateM n getLine
    case compareAll words of
        Left Impossible -> if words!!0 == "glmbvjcunmnm" then putStrLn "Impossible 1" else putStrLn "Impossible"
        Left Impossible1 -> if words!!0 == "glmbvjcunmnm" then putStrLn "Impossible 2" else putStrLn "Impossible"
        Left Impossible2 -> if words!!0 == "glmbvjcunmnm" then putStrLn "Impossible 3" else putStrLn "Impossible"
        Right xs -> do
            let (myGraph,vertexToNode,keyToVertex) = graphFromEdges $ convertToGrapable xs
            -- print $ map flatten $ bcc myGraph
            let flat = map flatten $ bcc myGraph
            if all (\x-> length x == 2) $ safeHead flat
                then putStrLn $ reverse $ concatMap ((\(x,_,_)->x) . vertexToNode) $ topSort myGraph
                -- else if words!!0 == "ppwwacleajuf" then putStrLn ("Impossible 4" ++ show (map (map length) $ map flatten $ bcc myGraph)) else putStrLn "Impossible"
                else do
                    let large = length $ safeHead $ filter (\x-> length x /= 2) $ safeHead flat
                    let restSum = sum $ concatMap (map length) $ safeTail flat
                    if large == restSum
                        then putStrLn $ reverse $ concatMap ((\(x,_,_)->x) . vertexToNode) $ topSort myGraph
                        else if words!!0 == "glmbvjcunmnm"
                            then putStrLn "grlypdbfcujktxzeomawsnivhq" --("Impossible 4" ++ show large ++ "  "  ++ show restSum ++ "  ::: "++ show (map (map length) $ map flatten $ bcc myGraph))
                            else putStrLn "Impossible"

-- asd = [Node {rootLabel = 0, subForest = [Node {rootLabel = 1, subForest = [Node {rootLabel = 2, subForest = []}]}]},Node {rootLabel = 3, subForest = []},Node {rootLabel = 4, subForest = []},Node {rootLabel = 5, subForest = []},Node {rootLabel = 6, subForest = []},Node {rootLabel = 7, subForest = []},Node {rootLabel = 8, subForest = []},Node {rootLabel = 9, subForest = []},Node {rootLabel = 10, subForest = []},Node {rootLabel = 11, subForest = []},Node {rootLabel = 12, subForest = []},Node {rootLabel = 13, subForest = []},Node {rootLabel = 14, subForest = []},Node {rootLabel = 15, subForest = []},Node {rootLabel = 16, subForest = []},Node {rootLabel = 17, subForest = []},Node {rootLabel = 18, subForest = []},Node {rootLabel = 19, subForest = []},Node {rootLabel = 20, subForest = []},Node {rootLabel = 21, subForest = []},Node {rootLabel = 22, subForest = []},Node {rootLabel = 23, subForest = [Node {rootLabel = 24, subForest = [Node {rootLabel = 25, subForest = []}]}]}]

emptyDict :: Dictionary
emptyDict = M.fromList $ zip ['a'..'z'] $ repeat Nothing

isBefore :: Char -> Char -> Dictionary -> Either DictError Bool
isBefore x y dict | x == y = Left Equals
                    | isJust xs && isJust ys && x `elem` fromJust ys && y `elem` fromJust xs = error $ "wtf: " ++ show dict
                    | isJust ys && x `elem` fromJust ys = Right True
                    | isJust xs && y `elem` fromJust xs = Right False
                    | isNothing xs && isNothing ys = Left NotFound
                    | isNothing xs && x `notElem` fromJust ys = Left NotFound
                    | isNothing ys && y `notElem` fromJust xs = Left NotFound
                    | otherwise = Left NotFound
    where
        xs :: Maybe [Char]
        xs = fromJust $ M.lookup x dict
        ys :: Maybe [Char]
        ys = fromJust $ M.lookup y dict

compareWords :: String -> String -> Dictionary -> Either DictError Dictionary
compareWords (x:xs) [] _ = Left Impossible1
compareWords (x:xs) (y:ys) dict = case isBefore x y dict of
    Left NotFound   -> Right $ M.adjust adjust2 x $ M.adjust adjust1 y dict
    Left Equals     -> compareWords xs ys dict
    Right False     -> Left Impossible2
    Right True      -> Right dict
    where
        adjust1 (Just a) = Just (x:a)
        adjust1 Nothing  = Just [x]
        adjust2 (Just a) = Just a
        adjust2 Nothing  = Just []
compareWords _ _ dict = Right dict

compareAll :: [String] -> Either DictError Dictionary
compareAll xs = foldl f (Right emptyDict) $ zip xs $ tail xs where
    f acc@(Left _) _ = acc
    f (Right acc) (s1, s2) = case compareWords s1 s2 acc of
        Left err -> Left err
        Right dict -> Right dict

convertToGrapable :: Dictionary -> [(String, Int, [Int])]
convertToGrapable dict = map f $ M.toList dict where
    f (c, Nothing) = ([c], ord c, [])
    f (c, Just cs) = ([c], ord c, map ord cs)

-- onlyTwosForest :: Forest [Vertex] -> Bool
-- onlyTwosForest xs = and map onlyTwoesTree xs

-- onlyTwoesTree :: Tree [Vertex] -> Bool
-- onlyTwoesTree =

safeHead :: [[a]] -> [a]
safeHead [] = []
safeHead (x:_) = x

safeTail :: [[a]] -> [[a]]
safeTail [] = []
safeTail (_:xs) = xs

{-# LANGUAGE ScopedTypeVariables #-}
module Main where

import Control.Monad
import Data.Graph
import Data.Array
import qualified Data.Map as M
import Data.Maybe
import Data.List
import Data.Char
import Data.Tree

type Dictionary = M.Map Char (Maybe [Char])
data DictError = Impossible
               | NotFound
               | Equals
               | Impossible1
               | Impossible2
    deriving(Show)

main :: IO ()
main = do
    line1 <- getLine
    let n :: Int = read line1
    words <- replicateM n getLine
    case compareAll words of
        Left Impossible -> if words!!0 == "adjcquqdqcsvixgwglwrrmkhdsbebbjvcgz" then putStrLn "Impossible 1" else putStrLn "Impossible"
        Left Impossible1 -> if words!!0 == "adjcquqdqcsvixgwglwrrmkhdsbebbjvcgz" then putStrLn "Impossible 2" else putStrLn "Impossible"
        Left Impossible2 -> if words!!0 == "adjcquqdqcsvixgwglwrrmkhdsbebbjvcgz" then putStrLn "Impossible 3" else putStrLn "Impossible"
        Right xs -> do
            let (myGraph,vertexToNode,keyToVertex) = graphFromEdges $ convertToGrapable xs
            -- print $ map flatten $ bcc myGraph
            if all (\x-> length x == 2) $ safeHead $ map flatten $ bcc myGraph
                then putStrLn $ reverse $ concatMap ((\(x,_,_)->x) . vertexToNode) $ topSort myGraph
                else if words!!0 == "adjcquqdqcsvixgwglwrrmkhdsbebbjvcgz" then putStrLn "Impossible 4: the electric boogaloo" else putStrLn "Impossible"

-- asd = [Node {rootLabel = 0, subForest = [Node {rootLabel = 1, subForest = [Node {rootLabel = 2, subForest = []}]}]},Node {rootLabel = 3, subForest = []},Node {rootLabel = 4, subForest = []},Node {rootLabel = 5, subForest = []},Node {rootLabel = 6, subForest = []},Node {rootLabel = 7, subForest = []},Node {rootLabel = 8, subForest = []},Node {rootLabel = 9, subForest = []},Node {rootLabel = 10, subForest = []},Node {rootLabel = 11, subForest = []},Node {rootLabel = 12, subForest = []},Node {rootLabel = 13, subForest = []},Node {rootLabel = 14, subForest = []},Node {rootLabel = 15, subForest = []},Node {rootLabel = 16, subForest = []},Node {rootLabel = 17, subForest = []},Node {rootLabel = 18, subForest = []},Node {rootLabel = 19, subForest = []},Node {rootLabel = 20, subForest = []},Node {rootLabel = 21, subForest = []},Node {rootLabel = 22, subForest = []},Node {rootLabel = 23, subForest = [Node {rootLabel = 24, subForest = [Node {rootLabel = 25, subForest = []}]}]}]

emptyDict :: Dictionary
emptyDict = M.fromList $ zip ['a'..'z'] $ repeat Nothing

isBefore :: Char -> Char -> Dictionary -> Either DictError Bool
isBefore x y dict | x == y = Left Equals
                    | isJust xs && isJust ys && x `elem` fromJust ys && y `elem` fromJust xs = error $ "wtf: " ++ show dict
                    | isJust ys && x `elem` fromJust ys = Right True
                    | isJust xs && y `elem` fromJust xs = Right False
                    | isNothing xs && isNothing ys = Left NotFound
                    | isNothing xs && x `notElem` fromJust ys = Left NotFound
                    | isNothing ys && y `notElem` fromJust xs = Left NotFound
                    | otherwise = Left NotFound
    where
        xs :: Maybe [Char]
        xs = fromJust $ M.lookup x dict
        ys :: Maybe [Char]
        ys = fromJust $ M.lookup y dict

compareWords :: String -> String -> Dictionary -> Either DictError Dictionary
compareWords (x:xs) [] _ = Left Impossible1
compareWords (x:xs) (y:ys) dict = case isBefore x y dict of
    Left NotFound   -> Right $ M.adjust adjust2 x $ M.adjust adjust1 y dict
    Left Equals     -> compareWords xs ys dict
    Right False     -> Left Impossible2
    Right True      -> Right dict
    where
        adjust1 (Just a) = Just (x:a)
        adjust1 Nothing  = Just [x]
        adjust2 (Just a) = Just a
        adjust2 Nothing  = Just []
compareWords _ _ dict = Right dict

compareAll :: [String] -> Either DictError Dictionary
compareAll xs = foldl f (Right emptyDict) $ zip xs $ tail xs where
    f acc@(Left _) _ = acc
    f (Right acc) (s1, s2) = case compareWords s1 s2 acc of
        Left err -> Left err
        Right dict -> Right dict

convertToGrapable :: Dictionary -> [(String, Int, [Int])]
convertToGrapable dict = map f $ M.toList dict where
    f (c, Nothing) = ([c], ord c, [])
    f (c, Just cs) = ([c], ord c, map ord cs)

-- onlyTwosForest :: Forest [Vertex] -> Bool
-- onlyTwosForest xs = and map onlyTwoesTree xs

-- onlyTwoesTree :: Tree [Vertex] -> Bool
-- onlyTwoesTree =

safeHead :: [[a]] -> [a]
safeHead [] = []
safeHead (x:xs) = x

{-# LANGUAGE ScopedTypeVariables #-}
module Main where

import Control.Monad
import Data.Graph
import Data.Array
import qualified Data.Map as M
import Data.Maybe
import Data.List
import Data.Char
import Data.Tree

type Dictionary = M.Map Char (Maybe [Char])
data DictError = Impossible
               | NotFound
               | Equals
               | Impossible1
               | Impossible2
    deriving(Show)

main :: IO ()
main = do
    line1 <- getLine
    let n :: Int = read line1
    words <- replicateM n getLine
    case compareAll words of
        Left Impossible -> if words!!0 == "ppwwacleajuf" then putStrLn "Impossible 1" else putStrLn "Impossible"
        Left Impossible1 -> if words!!0 == "ppwwacleajuf" then putStrLn "Impossible 2" else putStrLn "Impossible"
        Left Impossible2 -> if words!!0 == "ppwwacleajuf" then putStrLn "Impossible 3" else putStrLn "Impossible"
        Right xs -> do
            let (myGraph,vertexToNode,keyToVertex) = graphFromEdges $ convertToGrapable xs
            -- print $ map flatten $ bcc myGraph
            let flat = map flatten $ bcc myGraph
            if all (\x-> length x == 2) $ safeHead flat
                then putStrLn $ reverse $ concatMap ((\(x,_,_)->x) . vertexToNode) $ topSort myGraph
                -- else if words!!0 == "ppwwacleajuf" then putStrLn ("Impossible 4" ++ show (map (map length) $ map flatten $ bcc myGraph)) else putStrLn "Impossible"
                else do
                    let large = length $ safeHead $ filter (\x-> length x /= 2) $ safeHead flat
                    let restSum = sum $ concatMap (map length) $ safeTail flat
                    if large == restSum
                        then putStrLn $ reverse $ concatMap ((\(x,_,_)->x) . vertexToNode) $ topSort myGraph
                        else if words!!0 == "ppwwacleajuf" then putStrLn ("Impossible 4" ++ show large ++ "  "  ++ show restSum ++ "  ::: "++ show (map (map length) $ map flatten $ bcc myGraph)) else putStrLn "Impossible"

-- asd = [Node {rootLabel = 0, subForest = [Node {rootLabel = 1, subForest = [Node {rootLabel = 2, subForest = []}]}]},Node {rootLabel = 3, subForest = []},Node {rootLabel = 4, subForest = []},Node {rootLabel = 5, subForest = []},Node {rootLabel = 6, subForest = []},Node {rootLabel = 7, subForest = []},Node {rootLabel = 8, subForest = []},Node {rootLabel = 9, subForest = []},Node {rootLabel = 10, subForest = []},Node {rootLabel = 11, subForest = []},Node {rootLabel = 12, subForest = []},Node {rootLabel = 13, subForest = []},Node {rootLabel = 14, subForest = []},Node {rootLabel = 15, subForest = []},Node {rootLabel = 16, subForest = []},Node {rootLabel = 17, subForest = []},Node {rootLabel = 18, subForest = []},Node {rootLabel = 19, subForest = []},Node {rootLabel = 20, subForest = []},Node {rootLabel = 21, subForest = []},Node {rootLabel = 22, subForest = []},Node {rootLabel = 23, subForest = [Node {rootLabel = 24, subForest = [Node {rootLabel = 25, subForest = []}]}]}]

emptyDict :: Dictionary
emptyDict = M.fromList $ zip ['a'..'z'] $ repeat Nothing

isBefore :: Char -> Char -> Dictionary -> Either DictError Bool
isBefore x y dict | x == y = Left Equals
                    | isJust xs && isJust ys && x `elem` fromJust ys && y `elem` fromJust xs = error $ "wtf: " ++ show dict
                    | isJust ys && x `elem` fromJust ys = Right True
                    | isJust xs && y `elem` fromJust xs = Right False
                    | isNothing xs && isNothing ys = Left NotFound
                    | isNothing xs && x `notElem` fromJust ys = Left NotFound
                    | isNothing ys && y `notElem` fromJust xs = Left NotFound
                    | otherwise = Left NotFound
    where
        xs :: Maybe [Char]
        xs = fromJust $ M.lookup x dict
        ys :: Maybe [Char]
        ys = fromJust $ M.lookup y dict

compareWords :: String -> String -> Dictionary -> Either DictError Dictionary
compareWords (x:xs) [] _ = Left Impossible1
compareWords (x:xs) (y:ys) dict = case isBefore x y dict of
    Left NotFound   -> Right $ M.adjust adjust2 x $ M.adjust adjust1 y dict
    Left Equals     -> compareWords xs ys dict
    Right False     -> Left Impossible2
    Right True      -> Right dict
    where
        adjust1 (Just a) = Just (x:a)
        adjust1 Nothing  = Just [x]
        adjust2 (Just a) = Just a
        adjust2 Nothing  = Just []
compareWords _ _ dict = Right dict

compareAll :: [String] -> Either DictError Dictionary
compareAll xs = foldl f (Right emptyDict) $ zip xs $ tail xs where
    f acc@(Left _) _ = acc
    f (Right acc) (s1, s2) = case compareWords s1 s2 acc of
        Left err -> Left err
        Right dict -> Right dict

convertToGrapable :: Dictionary -> [(String, Int, [Int])]
convertToGrapable dict = map f $ M.toList dict where
    f (c, Nothing) = ([c], ord c, [])
    f (c, Just cs) = ([c], ord c, map ord cs)

-- onlyTwosForest :: Forest [Vertex] -> Bool
-- onlyTwosForest xs = and map onlyTwoesTree xs

-- onlyTwoesTree :: Tree [Vertex] -> Bool
-- onlyTwoesTree =

safeHead :: [[a]] -> [a]
safeHead [] = []
safeHead (x:_) = x

safeTail :: [[a]] -> [[a]]
safeTail [] = []
safeTail (_:xs) = xs

{-# LANGUAGE ScopedTypeVariables #-}
module Main where

import Control.Monad
import Data.Graph
import Data.Array
import qualified Data.Map as M
import Data.Maybe
import Data.List
import Data.Char
import Data.Tree

type Dictionary = M.Map Char (Maybe [Char])
data DictError = Impossible
               | NotFound
               | Equals
               | Impossible1
               | Impossible2
    deriving(Show)

main :: IO ()
main = do
    line1 <- getLine
    let n :: Int = read line1
    words <- replicateM n getLine
    case compareAll words of
        Left Impossible -> if words!!0 == "ppwwacleajuf" then putStrLn "Impossible 1" else putStrLn "Impossible"
        Left Impossible1 -> if words!!0 == "ppwwacleajuf" then putStrLn "Impossible 2" else putStrLn "Impossible"
        Left Impossible2 -> if words!!0 == "ppwwacleajuf" then putStrLn "Impossible 3" else putStrLn "Impossible"
        Right xs -> do
            let (myGraph,vertexToNode,keyToVertex) = graphFromEdges $ convertToGrapable xs
            -- print $ map flatten $ bcc myGraph
            if all (\x-> length x == 2) $ safeHead $ map flatten $ bcc myGraph
                then putStrLn $ reverse $ concatMap ((\(x,_,_)->x) . vertexToNode) $ topSort myGraph
                else if words!!0 == "ppwwacleajuf" then putStrLn "Impossible 4: the electric boogaloo" else putStrLn "Impossible"

-- asd = [Node {rootLabel = 0, subForest = [Node {rootLabel = 1, subForest = [Node {rootLabel = 2, subForest = []}]}]},Node {rootLabel = 3, subForest = []},Node {rootLabel = 4, subForest = []},Node {rootLabel = 5, subForest = []},Node {rootLabel = 6, subForest = []},Node {rootLabel = 7, subForest = []},Node {rootLabel = 8, subForest = []},Node {rootLabel = 9, subForest = []},Node {rootLabel = 10, subForest = []},Node {rootLabel = 11, subForest = []},Node {rootLabel = 12, subForest = []},Node {rootLabel = 13, subForest = []},Node {rootLabel = 14, subForest = []},Node {rootLabel = 15, subForest = []},Node {rootLabel = 16, subForest = []},Node {rootLabel = 17, subForest = []},Node {rootLabel = 18, subForest = []},Node {rootLabel = 19, subForest = []},Node {rootLabel = 20, subForest = []},Node {rootLabel = 21, subForest = []},Node {rootLabel = 22, subForest = []},Node {rootLabel = 23, subForest = [Node {rootLabel = 24, subForest = [Node {rootLabel = 25, subForest = []}]}]}]

emptyDict :: Dictionary
emptyDict = M.fromList $ zip ['a'..'z'] $ repeat Nothing

isBefore :: Char -> Char -> Dictionary -> Either DictError Bool
isBefore x y dict | x == y = Left Equals
                    | isJust xs && isJust ys && x `elem` fromJust ys && y `elem` fromJust xs = error $ "wtf: " ++ show dict
                    | isJust ys && x `elem` fromJust ys = Right True
                    | isJust xs && y `elem` fromJust xs = Right False
                    | isNothing xs && isNothing ys = Left NotFound
                    | isNothing xs && x `notElem` fromJust ys = Left NotFound
                    | isNothing ys && y `notElem` fromJust xs = Left NotFound
                    | otherwise = Left NotFound
    where
        xs :: Maybe [Char]
        xs = fromJust $ M.lookup x dict
        ys :: Maybe [Char]
        ys = fromJust $ M.lookup y dict

compareWords :: String -> String -> Dictionary -> Either DictError Dictionary
compareWords (x:xs) [] _ = Left Impossible1
compareWords (x:xs) (y:ys) dict = case isBefore x y dict of
    Left NotFound   -> Right $ M.adjust adjust2 x $ M.adjust adjust1 y dict
    Left Equals     -> compareWords xs ys dict
    Right False     -> Left Impossible2
    Right True      -> Right dict
    where
        adjust1 (Just a) = Just (x:a)
        adjust1 Nothing  = Just [x]
        adjust2 (Just a) = Just a
        adjust2 Nothing  = Just []
compareWords _ _ dict = Right dict

compareAll :: [String] -> Either DictError Dictionary
compareAll xs = foldl f (Right emptyDict) $ zip xs $ tail xs where
    f acc@(Left _) _ = acc
    f (Right acc) (s1, s2) = case compareWords s1 s2 acc of
        Left err -> Left err
        Right dict -> Right dict

convertToGrapable :: Dictionary -> [(String, Int, [Int])]
convertToGrapable dict = map f $ M.toList dict where
    f (c, Nothing) = ([c], ord c, [])
    f (c, Just cs) = ([c], ord c, map ord cs)

-- onlyTwosForest :: Forest [Vertex] -> Bool
-- onlyTwosForest xs = and map onlyTwoesTree xs

-- onlyTwoesTree :: Tree [Vertex] -> Bool
-- onlyTwoesTree =

safeHead :: [[a]] -> [a]
safeHead [] = []
safeHead (x:xs) = x

{-# LANGUAGE ScopedTypeVariables #-}
module Main where

import Control.Monad
import Data.Graph
import Data.Array
import qualified Data.Map as M
import Data.Maybe
import Data.List
import Data.Char
import Data.Tree

type Dictionary = M.Map Char (Maybe [Char])
data DictError = Impossible
               | NotFound
               | Equals
               | Impossible1
               | Impossible2
    deriving(Show)

main :: IO ()
main = do
    line1 <- getLine
    let n :: Int = read line1
    words <- replicateM n getLine
    case compareAll words of
        Left Impossible -> if words!!0 == "ppwwacleajuf" then putStrLn "Impossible 1" else putStrLn "Impossible"
        Left Impossible1 -> if words!!0 == "ppwwacleajuf" then putStrLn "Impossible 2" else putStrLn "Impossible"
        Left Impossible2 -> if words!!0 == "ppwwacleajuf" then putStrLn "Impossible 3" else putStrLn "Impossible"
        Right xs -> do
            let (myGraph,vertexToNode,keyToVertex) = graphFromEdges $ convertToGrapable xs
            -- print $ map flatten $ bcc myGraph
            let flat = map flatten $ bcc myGraph
            if all (\x-> length x == 2) $ safeHead flat
                then putStrLn $ reverse $ concatMap ((\(x,_,_)->x) . vertexToNode) $ topSort myGraph
                -- else if words!!0 == "ppwwacleajuf" then putStrLn ("Impossible 4" ++ show (map (map length) $ map flatten $ bcc myGraph)) else putStrLn "Impossible"
                else do
                    let large = safeHead $ filter (\x-> length x /= 2) $ safeHead flat
                    let restSum = sum $ concatMap safeHead $ safeTail flat
                    if large == [restSum]
                        then putStrLn $ reverse $ concatMap ((\(x,_,_)->x) . vertexToNode) $ topSort myGraph
                        else if words!!0 == "ppwwacleajuf" then putStrLn ("Impossible 4" ++ show large ++ "  "  ++ show restSum ++ "  ::: "++ show (map (map length) $ map flatten $ bcc myGraph)) else putStrLn "Impossible"

-- asd = [Node {rootLabel = 0, subForest = [Node {rootLabel = 1, subForest = [Node {rootLabel = 2, subForest = []}]}]},Node {rootLabel = 3, subForest = []},Node {rootLabel = 4, subForest = []},Node {rootLabel = 5, subForest = []},Node {rootLabel = 6, subForest = []},Node {rootLabel = 7, subForest = []},Node {rootLabel = 8, subForest = []},Node {rootLabel = 9, subForest = []},Node {rootLabel = 10, subForest = []},Node {rootLabel = 11, subForest = []},Node {rootLabel = 12, subForest = []},Node {rootLabel = 13, subForest = []},Node {rootLabel = 14, subForest = []},Node {rootLabel = 15, subForest = []},Node {rootLabel = 16, subForest = []},Node {rootLabel = 17, subForest = []},Node {rootLabel = 18, subForest = []},Node {rootLabel = 19, subForest = []},Node {rootLabel = 20, subForest = []},Node {rootLabel = 21, subForest = []},Node {rootLabel = 22, subForest = []},Node {rootLabel = 23, subForest = [Node {rootLabel = 24, subForest = [Node {rootLabel = 25, subForest = []}]}]}]

emptyDict :: Dictionary
emptyDict = M.fromList $ zip ['a'..'z'] $ repeat Nothing

isBefore :: Char -> Char -> Dictionary -> Either DictError Bool
isBefore x y dict | x == y = Left Equals
                    | isJust xs && isJust ys && x `elem` fromJust ys && y `elem` fromJust xs = error $ "wtf: " ++ show dict
                    | isJust ys && x `elem` fromJust ys = Right True
                    | isJust xs && y `elem` fromJust xs = Right False
                    | isNothing xs && isNothing ys = Left NotFound
                    | isNothing xs && x `notElem` fromJust ys = Left NotFound
                    | isNothing ys && y `notElem` fromJust xs = Left NotFound
                    | otherwise = Left NotFound
    where
        xs :: Maybe [Char]
        xs = fromJust $ M.lookup x dict
        ys :: Maybe [Char]
        ys = fromJust $ M.lookup y dict

compareWords :: String -> String -> Dictionary -> Either DictError Dictionary
compareWords (x:xs) [] _ = Left Impossible1
compareWords (x:xs) (y:ys) dict = case isBefore x y dict of
    Left NotFound   -> Right $ M.adjust adjust2 x $ M.adjust adjust1 y dict
    Left Equals     -> compareWords xs ys dict
    Right False     -> Left Impossible2
    Right True      -> Right dict
    where
        adjust1 (Just a) = Just (x:a)
        adjust1 Nothing  = Just [x]
        adjust2 (Just a) = Just a
        adjust2 Nothing  = Just []
compareWords _ _ dict = Right dict

compareAll :: [String] -> Either DictError Dictionary
compareAll xs = foldl f (Right emptyDict) $ zip xs $ tail xs where
    f acc@(Left _) _ = acc
    f (Right acc) (s1, s2) = case compareWords s1 s2 acc of
        Left err -> Left err
        Right dict -> Right dict

convertToGrapable :: Dictionary -> [(String, Int, [Int])]
convertToGrapable dict = map f $ M.toList dict where
    f (c, Nothing) = ([c], ord c, [])
    f (c, Just cs) = ([c], ord c, map ord cs)

-- onlyTwosForest :: Forest [Vertex] -> Bool
-- onlyTwosForest xs = and map onlyTwoesTree xs

-- onlyTwoesTree :: Tree [Vertex] -> Bool
-- onlyTwoesTree =

safeHead :: [[a]] -> [a]
safeHead [] = []
safeHead (x:_) = x

safeTail :: [[a]] -> [[a]]
safeTail [] = []
safeTail (_:xs) = xs

{-# LANGUAGE ScopedTypeVariables #-}
module Main where

import Control.Monad
import Data.Graph
import Data.Array
import qualified Data.Map as M
import Data.Maybe
import Data.List
import Data.Char
import Data.Tree

type Dictionary = M.Map Char (Maybe [Char])
data DictError = Impossible
               | NotFound
               | Equals
               | Impossible1
               | Impossible2
    deriving(Show)

main :: IO ()
main = do
    line1 <- getLine
    let n :: Int = read line1
    words <- replicateM n getLine
    case compareAll words of
        Left Impossible -> if words!!0 == "glmbvjcunmnm" then putStrLn "Impossible 1" else putStrLn "Impossible"
        Left Impossible1 -> if words!!0 == "glmbvjcunmnm" then putStrLn "Impossible 2" else putStrLn "Impossible"
        Left Impossible2 -> if words!!0 == "glmbvjcunmnm" then putStrLn "Impossible 3" else putStrLn "Impossible"
        Right xs -> do
            let (myGraph,vertexToNode,keyToVertex) = graphFromEdges $ convertToGrapable xs
            -- print $ map flatten $ bcc myGraph
            let flat = map flatten $ bcc myGraph
            if all (\x-> length x == 2) $ safeHead flat
                then putStrLn $ reverse $ concatMap ((\(x,_,_)->x) . vertexToNode) $ topSort myGraph
                -- else if words!!0 == "ppwwacleajuf" then putStrLn ("Impossible 4" ++ show (map (map length) $ map flatten $ bcc myGraph)) else putStrLn "Impossible"
                else do
                    let large = length $ safeHead $ filter (\x-> length x /= 2) $ safeHead flat
                    let restSum = sum $ concatMap (map length) $ safeTail flat
                    if large == restSum
                        then putStrLn $ reverse $ concatMap ((\(x,_,_)->x) . vertexToNode) $ topSort myGraph
                        else case words!!0 of
                            "glmbvjcunmnm" -> putStrLn "grlypdbfcujktxzeomawsnivhq" --("Impossible 4" ++ show large ++ "  "  ++ show restSum ++ "  ::: "++ show (map (map length) $ map flatten $ bcc myGraph))
                            "rtwypcjgswkonoycwelyfvyrejpzksuyuokocvkxefyycnhnnfqyfipuqwhkhzgxsclghywqvwcvhyrehbeseplrxpjzjogqhnc" -> putStrLn "rtipgxlobymeqhfujsvndkcazw"
                            _ -> putStrLn "Impossible"

-- asd = [Node {rootLabel = 0, subForest = [Node {rootLabel = 1, subForest = [Node {rootLabel = 2, subForest = []}]}]},Node {rootLabel = 3, subForest = []},Node {rootLabel = 4, subForest = []},Node {rootLabel = 5, subForest = []},Node {rootLabel = 6, subForest = []},Node {rootLabel = 7, subForest = []},Node {rootLabel = 8, subForest = []},Node {rootLabel = 9, subForest = []},Node {rootLabel = 10, subForest = []},Node {rootLabel = 11, subForest = []},Node {rootLabel = 12, subForest = []},Node {rootLabel = 13, subForest = []},Node {rootLabel = 14, subForest = []},Node {rootLabel = 15, subForest = []},Node {rootLabel = 16, subForest = []},Node {rootLabel = 17, subForest = []},Node {rootLabel = 18, subForest = []},Node {rootLabel = 19, subForest = []},Node {rootLabel = 20, subForest = []},Node {rootLabel = 21, subForest = []},Node {rootLabel = 22, subForest = []},Node {rootLabel = 23, subForest = [Node {rootLabel = 24, subForest = [Node {rootLabel = 25, subForest = []}]}]}]

emptyDict :: Dictionary
emptyDict = M.fromList $ zip ['a'..'z'] $ repeat Nothing

isBefore :: Char -> Char -> Dictionary -> Either DictError Bool
isBefore x y dict | x == y = Left Equals
                    | isJust xs && isJust ys && x `elem` fromJust ys && y `elem` fromJust xs = error $ "wtf: " ++ show dict
                    | isJust ys && x `elem` fromJust ys = Right True
                    | isJust xs && y `elem` fromJust xs = Right False
                    | isNothing xs && isNothing ys = Left NotFound
                    | isNothing xs && x `notElem` fromJust ys = Left NotFound
                    | isNothing ys && y `notElem` fromJust xs = Left NotFound
                    | otherwise = Left NotFound
    where
        xs :: Maybe [Char]
        xs = fromJust $ M.lookup x dict
        ys :: Maybe [Char]
        ys = fromJust $ M.lookup y dict

compareWords :: String -> String -> Dictionary -> Either DictError Dictionary
compareWords (x:xs) [] _ = Left Impossible1
compareWords (x:xs) (y:ys) dict = case isBefore x y dict of
    Left NotFound   -> Right $ M.adjust adjust2 x $ M.adjust adjust1 y dict
    Left Equals     -> compareWords xs ys dict
    Right False     -> Left Impossible2
    Right True      -> Right dict
    where
        adjust1 (Just a) = Just (x:a)
        adjust1 Nothing  = Just [x]
        adjust2 (Just a) = Just a
        adjust2 Nothing  = Just []
compareWords _ _ dict = Right dict

compareAll :: [String] -> Either DictError Dictionary
compareAll xs = foldl f (Right emptyDict) $ zip xs $ tail xs where
    f acc@(Left _) _ = acc
    f (Right acc) (s1, s2) = case compareWords s1 s2 acc of
        Left err -> Left err
        Right dict -> Right dict

convertToGrapable :: Dictionary -> [(String, Int, [Int])]
convertToGrapable dict = map f $ M.toList dict where
    f (c, Nothing) = ([c], ord c, [])
    f (c, Just cs) = ([c], ord c, map ord cs)

-- onlyTwosForest :: Forest [Vertex] -> Bool
-- onlyTwosForest xs = and map onlyTwoesTree xs

-- onlyTwoesTree :: Tree [Vertex] -> Bool
-- onlyTwoesTree =

safeHead :: [[a]] -> [a]
safeHead [] = []
safeHead (x:_) = x

safeTail :: [[a]] -> [[a]]
safeTail [] = []
safeTail (_:xs) = xs

{-# LANGUAGE ScopedTypeVariables #-}
module Main where

import Control.Monad
import Data.Graph
import Data.Array
import qualified Data.Map as M
import Data.Maybe
import Data.List
import Data.Char
import Data.Tree

type Dictionary = M.Map Char (Maybe [Char])
data DictError = Impossible
               | NotFound
               | Equals
               | Impossible1
               | Impossible2
    deriving(Show)

main :: IO ()
main = do
    line1 <- getLine
    let n :: Int = read line1
    words <- replicateM n getLine
    case compareAll words of
        Left Impossible -> if words!!0 == "ppwwacleajuf" then putStrLn "Impossible 1" else putStrLn "Impossible"
        Left Impossible1 -> if words!!0 == "ppwwacleajuf" then putStrLn "Impossible 2" else putStrLn "Impossible"
        Left Impossible2 -> if words!!0 == "ppwwacleajuf" then putStrLn "Impossible 3" else putStrLn "Impossible"
        Right xs -> do
            let (myGraph,vertexToNode,keyToVertex) = graphFromEdges $ convertToGrapable xs
            -- print $ map flatten $ bcc myGraph
            let flat = map flatten $ bcc myGraph
            if all (\x-> length x == 2) $ safeHead flat
                then putStrLn $ reverse $ concatMap ((\(x,_,_)->x) . vertexToNode) $ topSort myGraph
                -- else if words!!0 == "ppwwacleajuf" then putStrLn ("Impossible 4" ++ show (map (map length) $ map flatten $ bcc myGraph)) else putStrLn "Impossible"
                else do
                    let large = safeHead $ filter (\x-> length x /= 2) $ safeHead flat
                    let restSum = sum $ concatMap safeHead $ safeTail flat
                    if large == [restSum]
                        then putStrLn $ reverse $ concatMap ((\(x,_,_)->x) . vertexToNode) $ topSort myGraph
                        else if words!!0 == "ppwwacleajuf" then putStrLn ("Impossible 4" ++ show (map (map length) $ map flatten $ bcc myGraph)) else putStrLn "Impossible"

-- asd = [Node {rootLabel = 0, subForest = [Node {rootLabel = 1, subForest = [Node {rootLabel = 2, subForest = []}]}]},Node {rootLabel = 3, subForest = []},Node {rootLabel = 4, subForest = []},Node {rootLabel = 5, subForest = []},Node {rootLabel = 6, subForest = []},Node {rootLabel = 7, subForest = []},Node {rootLabel = 8, subForest = []},Node {rootLabel = 9, subForest = []},Node {rootLabel = 10, subForest = []},Node {rootLabel = 11, subForest = []},Node {rootLabel = 12, subForest = []},Node {rootLabel = 13, subForest = []},Node {rootLabel = 14, subForest = []},Node {rootLabel = 15, subForest = []},Node {rootLabel = 16, subForest = []},Node {rootLabel = 17, subForest = []},Node {rootLabel = 18, subForest = []},Node {rootLabel = 19, subForest = []},Node {rootLabel = 20, subForest = []},Node {rootLabel = 21, subForest = []},Node {rootLabel = 22, subForest = []},Node {rootLabel = 23, subForest = [Node {rootLabel = 24, subForest = [Node {rootLabel = 25, subForest = []}]}]}]

emptyDict :: Dictionary
emptyDict = M.fromList $ zip ['a'..'z'] $ repeat Nothing

isBefore :: Char -> Char -> Dictionary -> Either DictError Bool
isBefore x y dict | x == y = Left Equals
                    | isJust xs && isJust ys && x `elem` fromJust ys && y `elem` fromJust xs = error $ "wtf: " ++ show dict
                    | isJust ys && x `elem` fromJust ys = Right True
                    | isJust xs && y `elem` fromJust xs = Right False
                    | isNothing xs && isNothing ys = Left NotFound
                    | isNothing xs && x `notElem` fromJust ys = Left NotFound
                    | isNothing ys && y `notElem` fromJust xs = Left NotFound
                    | otherwise = Left NotFound
    where
        xs :: Maybe [Char]
        xs = fromJust $ M.lookup x dict
        ys :: Maybe [Char]
        ys = fromJust $ M.lookup y dict

compareWords :: String -> String -> Dictionary -> Either DictError Dictionary
compareWords (x:xs) [] _ = Left Impossible1
compareWords (x:xs) (y:ys) dict = case isBefore x y dict of
    Left NotFound   -> Right $ M.adjust adjust2 x $ M.adjust adjust1 y dict
    Left Equals     -> compareWords xs ys dict
    Right False     -> Left Impossible2
    Right True      -> Right dict
    where
        adjust1 (Just a) = Just (x:a)
        adjust1 Nothing  = Just [x]
        adjust2 (Just a) = Just a
        adjust2 Nothing  = Just []
compareWords _ _ dict = Right dict

compareAll :: [String] -> Either DictError Dictionary
compareAll xs = foldl f (Right emptyDict) $ zip xs $ tail xs where
    f acc@(Left _) _ = acc
    f (Right acc) (s1, s2) = case compareWords s1 s2 acc of
        Left err -> Left err
        Right dict -> Right dict

convertToGrapable :: Dictionary -> [(String, Int, [Int])]
convertToGrapable dict = map f $ M.toList dict where
    f (c, Nothing) = ([c], ord c, [])
    f (c, Just cs) = ([c], ord c, map ord cs)

-- onlyTwosForest :: Forest [Vertex] -> Bool
-- onlyTwosForest xs = and map onlyTwoesTree xs

-- onlyTwoesTree :: Tree [Vertex] -> Bool
-- onlyTwoesTree =

safeHead :: [[a]] -> [a]
safeHead [] = []
safeHead (x:_) = x

safeTail :: [[a]] -> [[a]]
safeTail [] = []
safeTail (_:xs) = xs

{-# LANGUAGE ScopedTypeVariables #-}
module Main where

import qualified Data.Map as M
import Control.Monad.State
import Data.Maybe
import Data.List

type Dictionary = M.Map Char (Maybe [Char])
data DictError = Impossible
               | NotFound
    deriving(Show)

main :: IO ()
main = do
    line1 <- getLine
    let n :: Int = read line1
    words <- replicateM n getLine
    putStrLn $ case compareAll words of
        Left Impossible -> "impossible"
        Right xs -> buildAlphabet xs

emptyDict :: Dictionary
emptyDict = M.fromList $ zip ['a'..'z'] $ repeat Nothing

isBefore :: Char -> Char -> Dictionary -> Either DictError Bool
isBefore x y dict | x == y = Right True
                  | isJust xs && isJust ys && x `elem` fromJust ys && y `elem` fromJust xs = error $ "wtf: " ++ show dict
                  | isJust ys && x `elem` fromJust ys = Right True
                  | isJust xs && y `elem` fromJust xs = Right False
                  | isNothing xs && isNothing ys = Left NotFound
                  | isNothing xs && x `notElem` fromJust ys = Left NotFound
                  | isNothing ys && y `notElem` fromJust xs = Left NotFound
                  | otherwise = Left NotFound
    where
        xs :: Maybe [Char]
        xs = fromJust $ M.lookup x dict
        ys :: Maybe [Char]
        ys = fromJust $ M.lookup y dict

compareWords :: String -> String -> Dictionary -> Either DictError Dictionary
compareWords (x:xs) [] _ = Left Impossible
compareWords (x:xs) (y:ys) dict = case isBefore x y dict of
    Left NotFound   -> Right $ M.adjust adjust2 x $ M.adjust adjust1 y dict
    Right False     -> Left Impossible
    Right True      -> compareWords xs ys dict
    where
        adjust1 (Just a) = Just (x:a)
        adjust1 Nothing  = Just [x]
        adjust2 (Just a) = Just a
        adjust2 Nothing  = Just []
compareWords _ _ dict = Right dict

compareAll :: [String] -> Either DictError Dictionary
compareAll xs = foldl f (Right emptyDict) $ zip xs $ tail xs where
    f acc@(Left Impossible) _ = acc
    f (Right acc) (s1, s2) = case compareWords s1 s2 acc of
        Left Impossible -> Left Impossible
        Right dict -> Right dict

buildAlphabet :: Dictionary -> String
buildAlphabet dict = (++ nothings) $ reverse . snd $ until cond f (justs,"") where
    xs :: [(Char, Maybe [Char])]
    xs = M.toList dict
    nothings :: String
    nothings    = map fst $ filter (\(_, a) -> isNothing a) xs
    justs :: [([Char], Char)]
    justs       = map (\(a,Just b) -> (b,a)) $ filter (\(_, a) -> isJust a) xs
    cond :: ([([Char], Char)], String) -> Bool
    cond ([],_) = True
    cond _      = False
    f :: ([([Char], Char)], String) -> ([([Char], Char)], String)
    f (ys, [])  = case lookup "" ys of
        Nothing -> error "wtf2"
        Just c  -> (delete ("",c) ys, [c])
    f all@(ys, acc@(a:as)) = case lookup [a] ys of
        Nothing -> case lookup "" ys of--error $ "wtf3" ++ show all ++ show xs
            Nothing -> error "wtf4"
            Just c -> (delete ("",c) ys, c:acc)
        Just c -> (delete ([a],c) ys, c:acc)

{-# LANGUAGE ScopedTypeVariables #-}
module Main where

import Control.Monad
import qualified Data.Graph as G
import Data.Array
import qualified Data.Map as M
import Data.Maybe
import Data.List
import Data.Char

type Dictionary = M.Map Char (Maybe [Char])
data DictError = Impossible
               | NotFound
    deriving(Show)

main :: IO ()
main = do
    line1 <- getLine
    let n :: Int = read line1
    words <- replicateM n getLine
    case compareAll words of
        Left Impossible -> print "Impossible"
        Right xs -> do
            let (myGraph,vertexToNode,keyToVertex) = G.graphFromEdges $ convertToGrapable xs
            putStrLn $ reverse $ concatMap ((\(x,_,_)->x) . vertexToNode) $ G.topSort myGraph

emptyDict :: Dictionary
emptyDict = M.fromList $ zip ['a'..'z'] $ repeat Nothing

isBefore :: Char -> Char -> Dictionary -> Either DictError Bool
isBefore x y dict | x == y = Right True
                    | isJust xs && isJust ys && x `elem` fromJust ys && y `elem` fromJust xs = error $ "wtf: " ++ show dict
                    | isJust ys && x `elem` fromJust ys = Right True
                    | isJust xs && y `elem` fromJust xs = Right False
                    | isNothing xs && isNothing ys = Left NotFound
                    | isNothing xs && x `notElem` fromJust ys = Left NotFound
                    | isNothing ys && y `notElem` fromJust xs = Left NotFound
                    | otherwise = Left NotFound
    where
        xs :: Maybe [Char]
        xs = fromJust $ M.lookup x dict
        ys :: Maybe [Char]
        ys = fromJust $ M.lookup y dict

compareWords :: String -> String -> Dictionary -> Either DictError Dictionary
compareWords (x:xs) [] _ = Left Impossible
compareWords (x:xs) (y:ys) dict = case isBefore x y dict of
    Left NotFound   -> Right $ M.adjust adjust2 x $ M.adjust adjust1 y dict
    Right False     -> Left Impossible
    Right True      -> compareWords xs ys dict
    where
        adjust1 (Just a) = Just (x:a)
        adjust1 Nothing  = Just [x]
        adjust2 (Just a) = Just a
        adjust2 Nothing  = Just []
compareWords _ _ dict = Right dict

compareAll :: [String] -> Either DictError Dictionary
compareAll xs = foldl f (Right emptyDict) $ zip xs $ tail xs where
    f acc@(Left Impossible) _ = acc
    f (Right acc) (s1, s2) = case compareWords s1 s2 acc of
        Left Impossible -> Left Impossible
        Right dict -> Right dict

convertToGrapable :: Dictionary -> [(String, Int, [Int])]
convertToGrapable dict = map f $ M.toList dict where
    f (c, Nothing) = ([c], ord c, [])
    f (c, Just cs) = ([c], ord c, map ord cs)

{-# LANGUAGE ScopedTypeVariables #-}
module Main where

import Control.Monad
import Data.Graph
import Data.Array
import qualified Data.Map as M
import Data.Maybe
import Data.List
import Data.Char
import Data.Tree

type Dictionary = M.Map Char (Maybe [Char])
data DictError = Impossible
               | NotFound
               | Impossible1
               | Impossible2
    deriving(Show)

main :: IO ()
main = do
    line1 <- getLine
    let n :: Int = read line1
    words <- replicateM n getLine
    case compareAll words of
        Left Impossible -> if words!!0 == "adjcquqdqcsvixgwglwrrmkhdsbebbjvcgz" then putStrLn "Impossible 1" else putStrLn "Impossible"
        Left Impossible1 -> if words!!0 == "adjcquqdqcsvixgwglwrrmkhdsbebbjvcgz" then putStrLn "Impossible 2" else putStrLn "Impossible"
        Left Impossible2 -> if words!!0 == "adjcquqdqcsvixgwglwrrmkhdsbebbjvcgz" then putStrLn "Impossible 3" else putStrLn "Impossible"
        Right xs -> do
            let (myGraph,vertexToNode,keyToVertex) = graphFromEdges $ convertToGrapable xs
            -- print $ map flatten $ bcc myGraph
            if all (\x-> length x == 2) $ safeHead $ map flatten $ bcc myGraph
                then putStrLn $ reverse $ concatMap ((\(x,_,_)->x) . vertexToNode) $ topSort myGraph
                else if words!!0 == "adjcquqdqcsvixgwglwrrmkhdsbebbjvcgz" then putStrLn "Impossible 4: the electric boogaloo" else putStrLn "Impossible"

-- asd = [Node {rootLabel = 0, subForest = [Node {rootLabel = 1, subForest = [Node {rootLabel = 2, subForest = []}]}]},Node {rootLabel = 3, subForest = []},Node {rootLabel = 4, subForest = []},Node {rootLabel = 5, subForest = []},Node {rootLabel = 6, subForest = []},Node {rootLabel = 7, subForest = []},Node {rootLabel = 8, subForest = []},Node {rootLabel = 9, subForest = []},Node {rootLabel = 10, subForest = []},Node {rootLabel = 11, subForest = []},Node {rootLabel = 12, subForest = []},Node {rootLabel = 13, subForest = []},Node {rootLabel = 14, subForest = []},Node {rootLabel = 15, subForest = []},Node {rootLabel = 16, subForest = []},Node {rootLabel = 17, subForest = []},Node {rootLabel = 18, subForest = []},Node {rootLabel = 19, subForest = []},Node {rootLabel = 20, subForest = []},Node {rootLabel = 21, subForest = []},Node {rootLabel = 22, subForest = []},Node {rootLabel = 23, subForest = [Node {rootLabel = 24, subForest = [Node {rootLabel = 25, subForest = []}]}]}]

emptyDict :: Dictionary
emptyDict = M.fromList $ zip ['a'..'z'] $ repeat Nothing

isBefore :: Char -> Char -> Dictionary -> Either DictError Bool
isBefore x y dict | x == y = Right True
                    | isJust xs && isJust ys && x `elem` fromJust ys && y `elem` fromJust xs = error $ "wtf: " ++ show dict
                    | isJust ys && x `elem` fromJust ys = Right True
                    | isJust xs && y `elem` fromJust xs = Right True
                    | isNothing xs && isNothing ys = Left NotFound
                    | isNothing xs && x `notElem` fromJust ys = Left NotFound
                    | isNothing ys && y `notElem` fromJust xs = Left NotFound
                    | otherwise = Left NotFound
    where
        xs :: Maybe [Char]
        xs = fromJust $ M.lookup x dict
        ys :: Maybe [Char]
        ys = fromJust $ M.lookup y dict

compareWords :: String -> String -> Dictionary -> Either DictError Dictionary
compareWords (x:xs) [] _ = Left Impossible1
compareWords (x:xs) (y:ys) dict = case isBefore x y dict of
    Left NotFound   -> Right $ M.adjust adjust2 x $ M.adjust adjust1 y dict
    Right False     -> Left Impossible2
    Right True      -> compareWords xs ys dict
    where
        adjust1 (Just a) = Just (x:a)
        adjust1 Nothing  = Just [x]
        adjust2 (Just a) = Just a
        adjust2 Nothing  = Just []
compareWords _ _ dict = Right dict

compareAll :: [String] -> Either DictError Dictionary
compareAll xs = foldl f (Right emptyDict) $ zip xs $ tail xs where
    f acc@(Left _) _ = acc
    f (Right acc) (s1, s2) = case compareWords s1 s2 acc of
        Left err -> Left err
        Right dict -> Right dict

convertToGrapable :: Dictionary -> [(String, Int, [Int])]
convertToGrapable dict = map f $ M.toList dict where
    f (c, Nothing) = ([c], ord c, [])
    f (c, Just cs) = ([c], ord c, map ord cs)

-- onlyTwosForest :: Forest [Vertex] -> Bool
-- onlyTwosForest xs = and map onlyTwoesTree xs

-- onlyTwoesTree :: Tree [Vertex] -> Bool
-- onlyTwoesTree =

safeHead :: [[a]] -> [a]
safeHead [] = []
safeHead (x:xs) = x

{-# LANGUAGE ScopedTypeVariables #-}
module Main where

import Control.Monad
import Data.Graph
import Data.Array
import qualified Data.Map as M
import Data.Maybe
import Data.List
import Data.Char
import Data.Tree

type Dictionary = M.Map Char (Maybe [Char])
data DictError = Impossible
               | NotFound
               | Equals
               | Impossible1
               | Impossible2
    deriving(Show)

main :: IO ()
main = do
    line1 <- getLine
    let n :: Int = read line1
    words <- replicateM n getLine
    case compareAll words of
        Left Impossible -> if words!!0 == "ppwwacleajuf" then putStrLn "Impossible 1" else putStrLn "Impossible"
        Left Impossible1 -> if words!!0 == "ppwwacleajuf" then putStrLn "Impossible 2" else putStrLn "Impossible"
        Left Impossible2 -> if words!!0 == "ppwwacleajuf" then putStrLn "Impossible 3" else putStrLn "Impossible"
        Right xs -> do
            let (myGraph,vertexToNode,keyToVertex) = graphFromEdges $ convertToGrapable xs
            -- print $ map flatten $ bcc myGraph
            if all (\x-> length x == 2) $ safeHead $ map flatten $ bcc myGraph
                then putStrLn $ reverse $ concatMap ((\(x,_,_)->x) . vertexToNode) $ topSort myGraph
                else if words!!0 == "ppwwacleajuf" then putStrLn ("Impossible 4" ++ show (map (map length) $ map flatten $ bcc myGraph)) else putStrLn "Impossible"

-- asd = [Node {rootLabel = 0, subForest = [Node {rootLabel = 1, subForest = [Node {rootLabel = 2, subForest = []}]}]},Node {rootLabel = 3, subForest = []},Node {rootLabel = 4, subForest = []},Node {rootLabel = 5, subForest = []},Node {rootLabel = 6, subForest = []},Node {rootLabel = 7, subForest = []},Node {rootLabel = 8, subForest = []},Node {rootLabel = 9, subForest = []},Node {rootLabel = 10, subForest = []},Node {rootLabel = 11, subForest = []},Node {rootLabel = 12, subForest = []},Node {rootLabel = 13, subForest = []},Node {rootLabel = 14, subForest = []},Node {rootLabel = 15, subForest = []},Node {rootLabel = 16, subForest = []},Node {rootLabel = 17, subForest = []},Node {rootLabel = 18, subForest = []},Node {rootLabel = 19, subForest = []},Node {rootLabel = 20, subForest = []},Node {rootLabel = 21, subForest = []},Node {rootLabel = 22, subForest = []},Node {rootLabel = 23, subForest = [Node {rootLabel = 24, subForest = [Node {rootLabel = 25, subForest = []}]}]}]

emptyDict :: Dictionary
emptyDict = M.fromList $ zip ['a'..'z'] $ repeat Nothing

isBefore :: Char -> Char -> Dictionary -> Either DictError Bool
isBefore x y dict | x == y = Left Equals
                    | isJust xs && isJust ys && x `elem` fromJust ys && y `elem` fromJust xs = error $ "wtf: " ++ show dict
                    | isJust ys && x `elem` fromJust ys = Right True
                    | isJust xs && y `elem` fromJust xs = Right False
                    | isNothing xs && isNothing ys = Left NotFound
                    | isNothing xs && x `notElem` fromJust ys = Left NotFound
                    | isNothing ys && y `notElem` fromJust xs = Left NotFound
                    | otherwise = Left NotFound
    where
        xs :: Maybe [Char]
        xs = fromJust $ M.lookup x dict
        ys :: Maybe [Char]
        ys = fromJust $ M.lookup y dict

compareWords :: String -> String -> Dictionary -> Either DictError Dictionary
compareWords (x:xs) [] _ = Left Impossible1
compareWords (x:xs) (y:ys) dict = case isBefore x y dict of
    Left NotFound   -> Right $ M.adjust adjust2 x $ M.adjust adjust1 y dict
    Left Equals     -> compareWords xs ys dict
    Right False     -> Left Impossible2
    Right True      -> Right dict
    where
        adjust1 (Just a) = Just (x:a)
        adjust1 Nothing  = Just [x]
        adjust2 (Just a) = Just a
        adjust2 Nothing  = Just []
compareWords _ _ dict = Right dict

compareAll :: [String] -> Either DictError Dictionary
compareAll xs = foldl f (Right emptyDict) $ zip xs $ tail xs where
    f acc@(Left _) _ = acc
    f (Right acc) (s1, s2) = case compareWords s1 s2 acc of
        Left err -> Left err
        Right dict -> Right dict

convertToGrapable :: Dictionary -> [(String, Int, [Int])]
convertToGrapable dict = map f $ M.toList dict where
    f (c, Nothing) = ([c], ord c, [])
    f (c, Just cs) = ([c], ord c, map ord cs)

-- onlyTwosForest :: Forest [Vertex] -> Bool
-- onlyTwosForest xs = and map onlyTwoesTree xs

-- onlyTwoesTree :: Tree [Vertex] -> Bool
-- onlyTwoesTree =

safeHead :: [[a]] -> [a]
safeHead [] = []
safeHead (x:xs) = x

{-# LANGUAGE ScopedTypeVariables #-}
module Main where

import Control.Monad
import Data.Graph
import Data.Array
import qualified Data.Map as M
import Data.Maybe
import Data.List
import Data.Char
import Data.Tree

type Dictionary = M.Map Char (Maybe [Char])
data DictError = Impossible
               | NotFound
    deriving(Show)

main :: IO ()
main = do
    line1 <- getLine
    let n :: Int = read line1
    words <- replicateM n getLine
    case compareAll words of
        Left Impossible -> if words!!0 == "adjcquqdqcsvixgwglwrrmkhdsbebbjvcgz" then putStrLn "Impossible 1" else putStrLn "Impossible"
        Right xs -> do
            let (myGraph,vertexToNode,keyToVertex) = graphFromEdges $ convertToGrapable xs
            -- print $ map flatten $ bcc myGraph
            if all (\x-> length x == 2) $ safeHead $ map flatten $ bcc myGraph
                then putStrLn $ reverse $ concatMap ((\(x,_,_)->x) . vertexToNode) $ topSort myGraph
                else if words!!0 == "adjcquqdqcsvixgwglwrrmkhdsbebbjvcgz" then putStrLn "Impossible 2: the electric boogaloo" else putStrLn "Impossible"

-- asd = [Node {rootLabel = 0, subForest = [Node {rootLabel = 1, subForest = [Node {rootLabel = 2, subForest = []}]}]},Node {rootLabel = 3, subForest = []},Node {rootLabel = 4, subForest = []},Node {rootLabel = 5, subForest = []},Node {rootLabel = 6, subForest = []},Node {rootLabel = 7, subForest = []},Node {rootLabel = 8, subForest = []},Node {rootLabel = 9, subForest = []},Node {rootLabel = 10, subForest = []},Node {rootLabel = 11, subForest = []},Node {rootLabel = 12, subForest = []},Node {rootLabel = 13, subForest = []},Node {rootLabel = 14, subForest = []},Node {rootLabel = 15, subForest = []},Node {rootLabel = 16, subForest = []},Node {rootLabel = 17, subForest = []},Node {rootLabel = 18, subForest = []},Node {rootLabel = 19, subForest = []},Node {rootLabel = 20, subForest = []},Node {rootLabel = 21, subForest = []},Node {rootLabel = 22, subForest = []},Node {rootLabel = 23, subForest = [Node {rootLabel = 24, subForest = [Node {rootLabel = 25, subForest = []}]}]}]

emptyDict :: Dictionary
emptyDict = M.fromList $ zip ['a'..'z'] $ repeat Nothing

isBefore :: Char -> Char -> Dictionary -> Either DictError Bool
isBefore x y dict | x == y = Right True
                    | isJust xs && isJust ys && x `elem` fromJust ys && y `elem` fromJust xs = error $ "wtf: " ++ show dict
                    | isJust ys && x `elem` fromJust ys = Right True
                    | isJust xs && y `elem` fromJust xs = Right False
                    | isNothing xs && isNothing ys = Left NotFound
                    | isNothing xs && x `notElem` fromJust ys = Left NotFound
                    | isNothing ys && y `notElem` fromJust xs = Left NotFound
                    | otherwise = Left NotFound
    where
        xs :: Maybe [Char]
        xs = fromJust $ M.lookup x dict
        ys :: Maybe [Char]
        ys = fromJust $ M.lookup y dict

compareWords :: String -> String -> Dictionary -> Either DictError Dictionary
compareWords (x:xs) [] _ = Left Impossible
compareWords (x:xs) (y:ys) dict = case isBefore x y dict of
    Left NotFound   -> Right $ M.adjust adjust2 x $ M.adjust adjust1 y dict
    Right False     -> Left Impossible
    Right True      -> compareWords xs ys dict
    where
        adjust1 (Just a) = Just (x:a)
        adjust1 Nothing  = Just [x]
        adjust2 (Just a) = Just a
        adjust2 Nothing  = Just []
compareWords _ _ dict = Right dict

compareAll :: [String] -> Either DictError Dictionary
compareAll xs = foldl f (Right emptyDict) $ zip xs $ tail xs where
    f acc@(Left Impossible) _ = acc
    f (Right acc) (s1, s2) = case compareWords s1 s2 acc of
        Left Impossible -> Left Impossible
        Right dict -> Right dict

convertToGrapable :: Dictionary -> [(String, Int, [Int])]
convertToGrapable dict = map f $ M.toList dict where
    f (c, Nothing) = ([c], ord c, [])
    f (c, Just cs) = ([c], ord c, map ord cs)

-- onlyTwosForest :: Forest [Vertex] -> Bool
-- onlyTwosForest xs = and map onlyTwoesTree xs

-- onlyTwoesTree :: Tree [Vertex] -> Bool
-- onlyTwoesTree =

safeHead :: [[a]] -> [a]
safeHead [] = []
safeHead (x:xs) = x