import scala.collection.mutable

object Main extends App {

  import scala.io.StdIn._
  import scala.math._

  val Array(h, w, s, t) = readLine.trim.split(' ')
  val state = Array.tabulate(h.toInt){_ ⇒ readLine.trim}
  val nodes = Array.tabulate(26){id ⇒ new Node(id)}
  val indices = Array.tabulate(26){i ⇒ i}.flatMap{i ⇒
    (0 until h.toInt).flatMap{y ⇒ (0 until w.toInt).map{x ⇒ Coordinate(x, y)}}.find{coord ⇒ state(coord.y)(coord.x) == ('A' + i)}.map{(_, i)}
  }
  for {(posA, i) ← indices
       (posB, j) ← indices if i != j}{
    if (posA.x == posB.x){
      if ((math.min(posA.y, posB.y) + 2 until math.max(posA.y, posB.y) - 1).forall{y ⇒ state(y)(posA.x) == '|'}) {
        nodes(i).addEdge(nodes(j))
        nodes(j).addEdge(nodes(i))
      }
    }else if (posA.y == posB.y){
      if ((math.min(posA.x, posB.x) + 2 until math.max(posA.x, posB.x) - 1).forall{x ⇒ state(posA.y)(x) == '-'}){
        nodes(i).addEdge(nodes(j))
        nodes(j).addEdge(nodes(i))
      }
    }
  }
  val minCost = Array.tabulate(26){_ ⇒ Int.MaxValue}.also{arr ⇒ arr(s.head - 'A') = 0}
  val queue = mutable.PriorityQueue()(Ordering.by[(Int, Int), Int](_._2).reverse).also{que ⇒ que.enqueue((s.head - 'A', 0))}
  while (queue.nonEmpty){
    val (top, distance) = queue.dequeue()
    if (minCost(top) == distance){
      for (next ← nodes(top).edges){
        if (minCost(next.id) - distance > 1) {
          minCost(next.id) = distance + 1
          queue.enqueue((next.id, minCost(next.id)))
        }
      }
    }
  }
  println(
    minCost(t.head - 'A')
  )

  case class Coordinate(x: Int, y: Int)
  class Node(val id: Int){
    private var mEdges: List[Node] = Nil
    def addEdge(to: Node): Unit = mEdges ::= to
    def edges: List[Node] = mEdges
  }
  implicit class Extension[T](val value :T){
    def also(func: T ⇒ Unit): T = {
      func(value)
      value
    }
    def let[R](func: T ⇒ R): R = func(value)
  }
}
