The University of Aizu Elementary School (Aizu University and Small) is famous as one of Japan's leading competition programmer training schools. Of course, it is essential to practice the algorithm even when attending an athletic meet.

Of course you, the director of the competitive programming department, want to win this tournament as well. This time we will focus on a certain competition.

A certain competition is a traditional competition held in Aizu, large and small. There are n cones in the schoolyard. Four colors of corn are available. Several pairs of cones are connected by arrows drawn with white lines. The arrow is attached to only one side, and an integer is also written.

Athletes act as a team of k people. Move in that direction from the cone at the starting point to the cone at the goal point on the arrow. However, each k person needs to have a different route to the goal point.

The fact that route 1 and route 2 are different means that

* Condition 1 If the number of arrows that pass through Route 1 and Route 2 is the same, there must be an i that has a different arrow that goes through the i-th in Route 1 and the arrow that goes through in the i-th in Route 2.
* Condition 2 The number of arrows passing through Route 1 and Route 2 is different.



It can be said that the route is different if any of the above is satisfied.

In addition, there is a prohibited color pattern in how to follow the cone, and players who include that pattern on the route from the start point to the goal point will be retired. However, other routes may follow any route, and may pass through the same cone (including the cone at the start point and the goal point) many times. In addition, the numbers written along with the arrows are added as scores. The competition is won by the team with more teammates reaching the goal cone with a smaller total score.

You, the director, should of course be able to solve this problem with programming. Find the maximum number of people who can move to the goal. Also, find the minimum score when you reach the maximum number of people.

However, if you can reduce the score as much as you want, output -1.



Input

The input consists of multiple test cases. The number of test cases does not exceed 20.


n
col1
col2
...
coln
m
a1 b1 c1
a2 b2 c2
...
am bm cm
k
pattern


n (2 ≤ n ≤ 100) represents the number of cones. coli (1 ≤ coli ≤ 4) indicates the color of the i-th cone. m (0 ≤ m ≤ 1,000) represents the number of arrows. ai is the number of the cone at the start of the arrow, bi is the number of the cone at the end, and ci is the score of the arrow. Also, up to 10 arrows can extend from one cone. (1 ≤ ai, bi ≤ n, -1,000 ≤ ci ≤ 1,000) k indicates the number of teams competing. (1 ≤ k ≤ 10) pattern is a character string consisting of numbers 1 to 4 with a length of 10 or less, and indicates a pattern in which movement is prohibited. The starting cone is the first cone and the nth cone is the goal. The numbers given in the input (n, col, m, a, b, c, k) are all integers. The end of the input is indicated by one line containing 0.

Output

The output consists of two integers separated by blanks. The first is the number of people that can be reached, and the second is its minimum cost. If you can reduce the score as much as you want, output one line containing only -1. If no one can reach it, output 0 0.

Example

Input

2
1
1
2
1 2 1
2 1 1
1
1111
2
1
1
2
1 2 1
2 1 1
1
11
2
1
1
2
1 2 1
2 1 1
10
1111
2
1
1
2
1 2 1
2 1 1
10
111111
2
1
1
2
1 2 -1
2 1 0
10
11
2
1
1
2
1 2 -1
2 1 0
10
1111
2
1
1
2
1 2 -1
2 1 0
10
12
2
1
1
2
1 2 -1
2 1 0
10
1111111111
0


Output

1 1
0 0
1 1
2 4
0 0
1 -1
-1
4 -10
#include<iostream>
#include<sstream>
#include<vector>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cassert>
using namespace std;

#define rep(i,n) for(int i=0;i<(int)n;i++)
#define fr(i,c) for(__typeof(c.begin()) i=c.begin();i!=c.end();i++)
#define pb push_back
#define mp make_pair
#define all(c) c.begin(),c.end()
#define dbg(x) cerr<<#x<<" = "<<(x)<<endl

typedef vector<int> vi;
typedef pair<int,int> pi;
typedef long long ll;
const int inf=(int)1e9;
const double EPS=1e-9, INF=1e12;

typedef int Weight;
struct Edge {
  int src, dst;
  Weight weight;
  Edge(int src, int dst, Weight weight) :
    src(src), dst(dst), weight(weight) { }
};
bool operator < (const Edge &e, const Edge &f) {
  return e.weight != f.weight ? e.weight > f.weight : // !!INVERSE!!
    e.src != f.src ? e.src < f.src : e.dst < f.dst;
}
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef vector<Weight> Array;
typedef vector<Array> Matrix;
// simpler method
vi k_shortestPath(const Graph &g, int s, int t, int k,int *h) {
  int n=g.size();
  vi dist[n];
  priority_queue<Edge> Q; Q.push(Edge(-1, s, 0));
  while (!Q.empty()) {
    Edge e = Q.top(); Q.pop();
    if (dist[e.dst].size() >= k) continue;
    dist[e.dst].push_back(e.weight);
    fr(f, g[e.dst]) Q.push(Edge(f->src, f->dst, f->weight+e.weight+h[f->src]-h[f->dst]));
  }
  rep(i,dist[t].size())dist[t][i]+=h[t]-h[s];
  return dist[t];
}
int *buildFail(char *p) {
  int m = strlen(p);
  int *fail = new int[m+1];
  int j = fail[0] = -1;
  for (int i = 1; i <= m; ++i) {
    while (j >= 0 && p[j] != p[i-1]) j = fail[j];
    fail[i] = ++j;
  }
  return fail;
}
int match(char *t, char *p, int *fail) {
  int n = strlen(t), m = strlen(p);
  int count = 0;
  for (int i = 0, k = 0; i < n; ++i) {
    while (k >= 0 && p[k] != t[i]) k = fail[k];
    if (++k >= m) {
      ++count; // match at t[i-m+1 .. i]
      k = fail[k];
    }
  }
  return count;
}


bool make_graph();
bool calc_potential();

int n,col[100],m,a[1000],b[1000],c[1000],k;
char ptn[20];
int V,s,t,h[1111];
Graph G,rG;
bool v[1111],rv[1111];

int main(){
	while(cin>>n,n){
		rep(i,n)cin>>col[i];
		cin>>m;
		rep(i,m)cin>>a[i]>>b[i]>>c[i];
		cin>>k>>ptn;
		
		if(!make_graph()){
			cout<<"0 0"<<endl; continue;
		}
		if(!calc_potential()){
			cout<<-1<<endl; continue;
		}
		vi ans=k_shortestPath(G,s,t,k,h);
		int sum=0;
		rep(i,ans.size())sum+=ans[i];
		cout<<ans.size()<<" "<<sum<<endl;
	}
	return 0;
}

void dfs(int c,const Graph &g,bool *v){
	v[c]=1;
	fr(i,g[c])if(!v[i->dst])dfs(i->dst,g,v);
}
bool calc_potential(){
	fill(h,h+V+1,0);
	rep(k,V)rep(i,V)if(v[i]&&rv[i])fr(e,G[i]){
		if(h[e->dst]>h[e->src]+e->weight){
			h[e->dst]=h[e->src]+e->weight;
			if(k==V-1) return 0; // negative cycle
		}
	}
	return 1;
}
inline void push(Graph &g,int src,int dst,int weight){
	g[src].pb(Edge(src,dst,weight));
}
bool make_graph(){
	int *fail=buildFail(ptn), len=strlen(ptn);
	G.clear(); rG.clear();
	V=n*(len+1)+1;
	s=0; t=V-1;
	while(s>=0&&ptn[s]-'0'!=col[0])s=fail[s];
	if(++s>=len)return 0;
	G.resize(V); rG.resize(V);
	
	vector<vector<pi> > e(n);
	rep(i,m)e[a[i]-1].pb(mp(b[i]-1,c[i]));
	
	rep(i,n)rep(j,len+1){
		fr(k,e[i]){
			int to=j;
			while(to>=0&&ptn[to]-'0'!=col[k->first])to=fail[to];
			if(++to>=len)continue;
			push(G,i*(len+1)+j,k->first*(len+1)+to,k->second);
			push(rG,k->first*(len+1)+to,i*(len+1)+j,0);
		}
	}
	rep(j,len){
		push(G,(n-1)*(len+1)+j,t,0);
		push(rG,t,(n-1)*(len+1)+j,0);
	}
	/*
	dbg(len); dbg(t);
	rep(i,n)rep(j,len+1){
		cerr<<"i: "<<i<<" j: "<<j<<endl;
		fr(k,G[i*(len+1)+j])cerr<<k->src<<" "<<k->dst<<" "<<k->weight<<endl;
	}
	*/
	rep(i,V)v[i]=rv[i]=0;
	dfs(s,G,v); dfs(t,rG,rv);
	return v[t]&&rv[s];
}