//include
//------------------------------------------
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <climits>
#include <queue>

using namespace std;

//typedef
//------------------------------------------
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<int, int> PII;
typedef long long LL;

//container util
//------------------------------------------
#define ALL(a)  (a).begin(),(a).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define PB push_back
#define MP make_pair
#define SZ(a) int((a).size())
#define EACH(i,c) for(typeof((c).begin()) i=(c).begin(); i!=(c).end(); ++i)
#define EXIST(s,e) ((s).find(e)!=(s).end())
#define SORT(c) sort((c).begin(),(c).end())

//repetition
//------------------------------------------
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n)  FOR(i,0,n)

//constant
//--------------------------------------------
const double EPS = 1e-10;
const double PI  = acos(-1.0);
const int INF = 1e9;

VS maze[1<<10];
char rev(char c){
  switch(c){
  case '_': return '^';
  case '^': return '_';
	/*
  case '%': return '$';
  case '$': return '%';
  case '&': return '~';
  case '~': return '&';
	*/
  }
  if('A' <= c && c <= 'Z') return 'a'+c-'A';
  return 'A'+c-'a';
}

int dist[1<<11][51][51];
int dx[4] = {-1,1,0,0};
int dy[4] = {0,0,-1,1};

int main(){
  cin.tie(0);
  ios_base::sync_with_stdio(false);

  int W, H, S; cin >> W >> H;
  vector<VS> mapd(12, VS(H));
  REP(i,H) cin >> mapd[0][i];
  cin >> S;
  REP(i,S) REP(j,H)
	cin >> mapd[i+1][j];

  int sy, sx, gy, gx;
  REP(y,H) REP(x,W)
	if(mapd[0][y][x] == '%')
	  sx = x, sy = y, mapd[0][y][x] = '_';
	else if(mapd[0][y][x] == '&')
	  gx = x, gy = y, mapd[0][y][x] = '_';
					   
  REP(b,1<<S){
	maze[b].assign(H, string(W, ' '));
	REP(y,H) REP(x,W){
	  char c = mapd[0][y][x];
	  if(c == '#' || c == '|')
		maze[b][y][x] = c;
	  else{
		bool on = false;
		REP(i,S)
		  if(b>>i&1 && mapd[i+1][y][x] == '*')
			on ^= true;
		if(!on) maze[b][y][x] = c;
		else maze[b][y][x] = rev(c);
	  }
	}
  }

  /*
  REP(b,1<<S){
	REP(y,H){
	  REP(x,W) cout << maze[b][y][x];
	  cout<<endl;
	}
	cout << "----------------"<<endl;
  }
  */

  queue<tuple<int,int,int>> q;
  q.push(make_tuple(sx,sy,0));
  fill((int*)dist, (int*)dist+(1<<11)*51*51, INF);
  dist[0][sy][sx] = 0;
  while(!q.empty()){
	int x, y, s, up;
	tie(x,y,s) = q.front(); q.pop();
	up = s >> 10 & 1;
	int ms = s ^ (up << 10);

	REP(i,4){
	  int tx = x + dx[i], ty = y + dy[i];
	  if(dist[s][ty][tx] < INF) continue;
	  char tc = maze[ms][ty][tx];
	  if(tc == '#') continue;
	  if(!up){
		if(tc == '^' || ('A' <= tc && tc <= 'Z')) continue;
	  }
	  else{
		if(tc == '_' || ('a' <= tc && tc <= 'z')) continue;
	  }
	  dist[s][ty][tx] = dist[s][y][x] + 1;
	  q.push(make_tuple(tx,ty,s));
	}

	char c = maze[ms][y][x];
	if(c == '|'){
	  if(dist[s^(1<<10)][y][x] == INF){
		dist[s^(1<<10)][y][x] = dist[s][y][x] + 1;
		q.push(make_tuple(x,y,s^(1<<10)));
	  }
	}
	else if('a' <= c && c <= 'z'){
	  int b = 1 << (c-'a');
	  if(maze[ms^b][y][x] != maze[ms][y][x])
		b |= 1 << 10;
	  if(dist[s^b][y][x] == INF){
		dist[s^b][y][x] = dist[s][y][x] + 1;
		q.push(make_tuple(x,y,s^b));
	  }
	}
	else if('A' <= c && c <= 'Z'){
	  int b = 1 << (c-'A');
	  if(maze[ms^b][y][x] != maze[ms][y][x])
		b |= 1 << 10;
	  if(dist[s^b][y][x] == INF){
		dist[s^b][y][x] = dist[s][y][x] + 1;
		q.push(make_tuple(x,y,s^b));
	  }
	}
  }

  int ans = INF;
  for(int s=0;s<1<<11;++s)
	ans = min(ans, dist[s][gy][gx]);

  cout << (ans < INF? ans: -1) << endl;
  
  return 0;
}

Measured memory_bytes: 27792