package main

/*
   BFS
   分别从S、E出发,把可达位置分别标记为S、E
   遍历过程中判断是否有同一行/列或相邻行/列内既含有S,也含有E
*/

import (
	"fmt"
)

type Node struct {
	i, j int
}

var nS, nE, nH byte = byte('S'), byte('E'), byte('#')

func isAdjoin(a, b int) bool { // 是否相邻
    if a > b{
        return a - b <= 1
    }
    return b - a <= 1
}

func main() {
	var n, m int
	fmt.Scanf("%d %d", &n, &m)
	var k = make([][]byte, n)
	var s string
	var S_i, S_j, E_i, E_j int
	for i := 0; i < n; i++ {
		fmt.Scanf("%s", &s)
		k[i] = make([]byte, m)
		k[i] = []byte(s)
		for j := 0; j < m; j++ {
			if k[i][j] == nS {
				S_i = i
				S_j = j
			}
			if k[i][j] == nE {
				E_i = i
				E_j = j
			}
		}
	}
	if isAdjoin(S_i, E_i) || isAdjoin(S_j, E_j) { // 相邻或同行或同列
		fmt.Println("YES")
		return
	}

    var si, sj = make([]bool, n),make([]bool, m) // 记录某行某列是否S可达 
    si[S_i] = true
    sj[S_j] = true

	dist := [][]int{{1, 0}, {-1, 0}, {0, -1}, {0, 1}} // 四个方向操作
	var cur Node
	var ni, nj int
	// 先从S开始遍历
	queue := []Node{{S_i, S_j}}
	for len(queue) > 0 {
		cur = queue[0]
		queue = queue[1:]

		for _, d := range dist {
			ni = cur.i + d[0]
			nj = cur.j + d[1]
			if ni < 0 || ni >= n || nj < 0 || nj >= m || k[ni][nj] == nS || k[ni][nj] == nH {
				continue
			}
			if k[ni][nj] == nE || isAdjoin(ni, E_i) || isAdjoin(nj, E_j) { // 与E相邻或同行或同列
				fmt.Println("YES")
				return
			}
			k[ni][nj] = nS
            si[ni],sj[nj] = true, true
			queue = append(queue, Node{ni, nj})
		}
	}

	// 再从E开始遍历
	queue = []Node{{E_i, E_j}}
	for len(queue) > 0 {
		cur = queue[0]
		queue = queue[1:]

		for _, d := range dist {
			ni = cur.i + d[0]
			nj = cur.j + d[1]
			if ni < 0 || ni >= n || nj < 0 || nj >= m || k[ni][nj] == nE || k[ni][nj] == nH {
				continue
			}
			if k[ni][nj] == nS || 
                si[ni] || (ni-1>=0&&si[ni-1]) || (ni+1<n&&si[ni+1]) || 
                sj[nj] || (nj-1>=0&&sj[nj-1]) || (nj+1<m&&sj[nj+1]) { // 与S可达的位置相邻或同行或同列
				fmt.Println("YES")
				return
			}
			k[ni][nj] = nE
			queue = append(queue, Node{ni, nj})
		}
	}

    // 都没法满足,无法可达
	fmt.Print("NO")
}