Problem:
Score : 700 points

Problem Statement

There is an H \times W grid (H vertical, W horizontal), where each square contains a lowercase English letter.
Specifically, the letter in the square at the i-th row and j-th column is equal to the j-th character in the string S_i.

Snuke can apply the following operation to this grid any number of times:

Choose two different rows and swap them. Or, choose two different columns and swap them.

Snuke wants this grid to be symmetric.
That is, for any 1 \leq i \leq H and 1 \leq j \leq W, the letter in the square at the i-th row and j-th column and the letter in the square at the (H + 1 - i)-th row and (W + 1 - j)-th column should be equal.

Determine if Snuke can achieve this objective.

Constraints

1 \leq H \leq 12

1 \leq W \leq 12

|S_i| = W

S_i consists of lowercase English letters.

Input

Input is given from Standard Input in the following format:

H W
S_1
S_2
:
S_H

Output

If Snuke can make the grid symmetric, print YES; if he cannot, print NO.

Sample Input 1

2 3
arc
rac

Sample Output 1

YES

If the second and third columns from the left are swapped, the grid becomes symmetric, as shown in the image below:

Sample Input 2

3 7
atcoder
regular
contest

Sample Output 2

NO

Sample Input 3

12 12
bimonigaloaf
faurwlkbleht
dexwimqxzxbb
lxdgyoifcxid
ydxiliocfdgx
nfoabgilamoi
ibxbdqmzxxwe
pqirylfrcrnf
wtehfkllbura
yfrnpflcrirq
wvcclwgiubrk
lkbrwgwuiccv

Sample Output 3

YES

Solution in Haskell (GHC 7.10.3) (judge verdict: Accepted)

import Control.Monad
import Data.Array
import Data.List
import Data.Tuple (swap)
import Debug.Trace

import Test.QuickCheck

main = do
  [h,w] <- fmap (map read . words) getLine
  wss <- replicateM h getLine
  let tab = listArray ((1,1),(h,w)) (concat wss)
  putStrLn (solve tab)


type Table = Array (IxRow,IxCol) Char
type IxRow = Int
type IxCol = Int


showTable :: Table -> String
showTable tab =
  unlines [[ tab!(r,c) | c<-[ca..cz]] | r<-[ra..rz]]
  where
    ((ra,ca),(rz,cz)) = bounds tab

findElem :: IxRow -> Char -> Table -> [IxRow]
findElem r x tab =
  elemIndices x (elems (ixmap ((r,ca),(r,cz)) id tab))
  where
    ((ra,ca),(rz,cz)) = bounds tab

transposeTable :: Table -> Table
transposeTable tab =
  ixmap ((ca,ra),(cz,rz)) swap tab
  where
    ((ra,ca),(rz,cz)) = bounds tab

swapRow :: IxRow -> IxRow -> Table-> Table
swapRow i j tab =
  ixmap (bounds tab) f tab
  where
    f (r,c) | r == i    = (j,c)
            | r == j    = (i,c)
            | otherwise = (r,c)

swapCol :: IxCol -> IxCol -> Table -> Table
swapCol i j tab =
  ixmap (bounds tab) f tab
  where
    f (r,c) | c == i    = (r,j)
            | c == j    = (r,i)
            | otherwise = (r,c)

solve :: Table -> String
solve tab =
--  trace (unlines $ map showTable rowSolved) $
  if null [t| t<-rowColSolved, checkSymmetric t] then "NO" else "YES"
  where
    ((ra,ca),(rz,cz)) = bounds tab

    rowSolved = concat [solveRow 1 r tab | r<-[ra..rz]]
    rowColSolved = concat [solveRow 1 c t' | t <- rowSolved, let t' = transposeTable t, c<-[ca..cz]]

solveRow :: IxRow -> IxRow -> Table -> [Table]
solveRow r1 r2 tab =
  go ca cz [] tab
  where
    go c1 c2 center t
--      | trace (showTable t ++ show (c1,cz)) False = undefined
      | length center > 1 = []
      | c1 >= c2  = [t]
      | otherwise = let ts = solveRowCol r1 r2 c1 c2 t
                    in if null ts && odd cz
                         then go c1 c2 (c1:center) (swapCol c1 (cz`div`2+1) t)
                         else concatMap (go (c1+1) (c2-1) center) ts

    ((ra,ca),(rz,cz)) = bounds tab

solveRowCol :: IxRow -> IxRow -> IxCol -> IxCol -> Table -> [Table]
solveRowCol r1 r2 c1 c2 tab
  | trace (showTable tab ++ show (r1,r2,c1,c2)) False = undefined
  | c1 == c2  = [tab]
  | otherwise = [swapCol c c2 tab |c<-[c1+1..c2], isSymmetric r1 r2 c1 c tab]

isSymmetric :: IxRow -> IxRow -> IxCol -> IxCol -> Table -> Bool
isSymmetric r1 r2 c1 c2 tab =
  x11 == x22 && x21 == x12
  where
    x11 = tab!(r1,c1)
    x21 = tab!(r2,c1)
    x12 = tab!(r1,c2)
    x22 = tab!(r2,c2)

checkSymmetric :: Table -> Bool
checkSymmetric tab =
  and [isSymmetric r (rz-r+1) c (cz-c+1) tab | r<-[ra..rz], r<=rz-r+1, c<-[ca..cz]]
  where
    ((ra,ca),(rz,cz)) = bounds tab