#include <bits/stdc++.h>
#pragma GCC optimize("O3")
using namespace std;
using ll = long long;
using pii = pair<int, int>;
using vi = vector<int>;
using ld = long double;
struct Node {
  vi to;
  int lk;
  ll w;
  Node() : to(14), lk(0), w(0) {}
};
vector<Node> au(1);
int sz = 1;
void add(const string& s, int w) {
  int v = 0;
  for (char c : s) {
    c -= 'a';
    if (!au[v].to[c]) {
      au[v].to[c] = sz++;
      au.push_back(Node());
    }
    v = au[v].to[c];
  }
  au[v].w += w;
}
void build() {
  queue<int> q;
  q.push(0);
  while (!q.empty()) {
    int v = q.front();
    q.pop();
    au[v].w += au[au[v].lk].w;
    for (char kek = 'a'; kek <= 'n'; kek++) {
      auto c = kek - 'a';
      if (au[v].to[c]) {
        int u = au[v].to[c];
        au[u].lk = (v ? au[au[v].lk].to[c] : 0);
        q.push(u);
      } else {
        au[v].to[c] = au[au[v].lk].to[c];
      }
    }
  }
}
ll dp[1 << 14][1001];
ll dp_new[1 << 14][1001];
const ll inf = 1e18 + 228;
int32_t main() {
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  int k;
  cin >> k;
  for (int i = 0; i < k; i++) {
    string s;
    int w;
    cin >> s >> w;
    add(s, w);
  }
  build();
  string s;
  cin >> s;
  string KEK = s;
  int n = (int)((s).size());
  const ll inf = 1e18 + 228;
  vi bpc(1 << 14);
  for (int msk = 1; msk < (1 << 14); msk++) {
    bpc[msk] = 1 + bpc[msk & (msk - 1)];
  }
  vi qps;
  ll ans_add = 0;
  int v = 0;
  int lst = -sz;
  for (int i = 0; i < n; i++) {
    if (s[i] == '?')
      qps.push_back(i), v = 0, lst = i;
    else
      v = au[v].to[s[i] - 'a'];
    if (i - lst >= sz) ans_add += au[v].w;
  }
  for (int i = 0; i < (1 << 14); i++) {
    for (int j = 0; j < sz; j++) {
      dp[i][j] = dp_new[i][j] = -inf;
    }
  }
  dp[0][0] = 0;
  int pi = (qps.empty() || qps[0] < sz ? 0 : qps[0] - sz);
  int yet = 0;
  vector<vi> msks(15);
  for (int m = 0; m < (1 << 14); m++) {
    msks[bpc[m]].push_back(m);
  }
  for (int i : qps) {
    pi = max(pi, i - sz);
    for (int m : msks[yet]) {
      for (int s = 0; s < sz; s++) {
        dp_new[m][s] = -inf;
      }
    }
    for (int s = 0; s < sz; s++) {
      int ss = s;
      for (int j = pi; j < i; j++) {
        ss = au[ss].to[KEK[j] - 'a'];
      }
      for (int m : msks[yet]) {
        if (dp[m][s] == -inf) continue;
        dp_new[m][ss] = max(dp_new[m][ss], dp[m][s]);
      }
    }
    memcpy(dp, dp_new, sizeof(dp));
    for (int m : msks[yet]) {
      for (int b = 0; b < 14; b++) {
        if (m >> b & 1) continue;
        int mm = m | (1 << b);
        for (int s = 0; s < sz; s++) {
          if (dp[m][s] == -inf) continue;
          int ss = au[s].to[b];
          dp[mm][ss] = max(dp[mm][ss], dp[m][s] + au[ss].w);
        }
      }
    }
    yet++;
    pi = i + 1;
    while (pi < n && pi - i < sz && s[pi] != '?') pi++;
    for (int s = 0; s < sz; s++) {
      int ss = s;
      ll add = 0;
      for (int j = i + 1; j < pi; j++) {
        ss = au[ss].to[KEK[j] - 'a'];
        add += au[ss].w;
      }
      for (int m : msks[yet]) {
        if (dp[m][s] == -inf) continue;
        dp_new[m][ss] = max(dp_new[m][ss], dp[m][s] + add);
      }
    }
    memcpy(dp, dp_new, sizeof(dp));
  }
  ll ans = -inf;
  for (int i = 0; i < (1 << 14); i++) {
    if (bpc[i] != (int)((qps).size())) continue;
    for (int j = 0; j < sz; j++) {
      if (ans < dp[i][j]) {
        ans = dp[i][j];
      }
    }
  }
  cout << ans + ans_add;
}
