#include <bits/stdc++.h>
using namespace std;
const long long INF = 10000000000000000LL;
struct AC {
  int N, P;
  const int A = 14;
  vector<vector<int> > next;
  vector<int> link, out_link;
  vector<vector<int> > out;
  vector<int> cost;
  AC() : N(0), P(0) { node(); }
  int node() {
    next.emplace_back(A, 0);
    link.emplace_back(0);
    out.emplace_back(0);
    out_link.emplace_back(0);
    return N++;
  }
  inline int get(char c) { return c - 'a'; }
  void insert(const string &T, int cs) {
    int u = 0;
    for (char c : T) {
      if (!next[u][get(c)]) next[u][get(c)] = node();
      u = next[u][get(c)];
    }
    out[u].push_back(P);
    cost.push_back(cs);
    P++;
  }
  void build() {
    queue<int> q;
    for (q.push(0); !q.empty();) {
      int u = q.front();
      q.pop();
      for (int c = 0; c < A; ++c) {
        int v = next[u][c];
        if (!v)
          next[u][c] = next[link[u]][c];
        else {
          link[v] = u ? next[link[u]][c] : 0;
          out_link[v] = out[link[v]].empty() ? out_link[link[v]] : link[v];
          q.push(v);
        }
      }
    }
  }
  int pp[1010];
  bool vpp[1010];
  int path(int cur) {
    if (cur == 0) return 0;
    if (vpp[cur]) return pp[cur];
    vpp[cur] = true;
    for (auto e : out[cur]) pp[cur] += cost[e];
    return pp[cur] = pp[cur] + path(out_link[cur]);
  }
  pair<long long, long long> traverse(const string &s, int u, int a) {
    long long ret = 0;
    for (int i = a; i < (int)s.size(); i++) {
      char c = s[i];
      if (c == '?') break;
      u = next[u][get(c)];
      ret += path(u);
    }
    return {u, ret};
  }
};
string s;
AC aho;
int qc;
vector<int> q;
int pos[20];
pair<long long, long long> pre[1010][16];
bool vpre[1010][16];
pair<long long, long long> get_cost(int nd, int p) {
  if (vpre[nd][p]) return pre[nd][p];
  vpre[nd][p] = true;
  return pre[nd][p] = aho.traverse(s, nd, pos[p] + 1);
}
long long dp[1010][(1 << 14) + 5];
bool vdp[1010][(1 << 14) + 5];
long long call(int nd, int mask) {
  int p = __builtin_popcount(mask);
  if (p == qc) return 0;
  if (vdp[nd][mask]) return dp[nd][mask];
  vdp[nd][mask] = true;
  long long ret = -INF;
  p++;
  int nxt;
  pair<long long, long long> jump;
  for (char ch = 'a'; ch <= 'n'; ch++) {
    if (mask & (1 << (ch - 'a'))) continue;
    nxt = aho.next[nd][aho.get(ch)];
    jump = get_cost(nxt, p);
    ret = max(ret, jump.second + aho.path(nxt) +
                       call(jump.first, mask | (1 << (ch - 'a'))));
  }
  return dp[nd][mask] = ret;
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  int n;
  cin >> n;
  int c;
  for (int i = 1; i <= n; i++) {
    cin >> s >> c;
    aho.insert(s, c);
  }
  aho.build();
  cin >> s;
  q.push_back(-1);
  pos[0] = -1;
  for (int i = 0; i < (int)s.size(); i++) {
    if (s[i] == '?') {
      qc++;
      pos[q.size()] = i;
      q.push_back(i);
    }
  }
  pair<long long, long long> cur = get_cost(0, 0);
  long long ans = cur.second + call(cur.first, 0);
  cout << ans << endl;
  return 0;
}
