#include <bits/stdc++.h>
using namespace std;
namespace RA {
int r(int p) { return 1ll * rand() * rand() % p; }
int r(int L, int R) { return r(R - L + 1) + L; }
}  // namespace RA
const int SZ = 1020, ALP = 14, N = 4e5 + 5;
int k;
int tot, tr[SZ][ALP], fail[SZ];
long long val[SZ], F[1 << ALP][SZ], G[1 << ALP][SZ];
void insert(char *s, int x) {
  int u = 0;
  while (*s) {
    int c = *s - 'a';
    if (!tr[u][c]) tr[u][c] = ++tot;
    u = tr[u][c];
    ++s;
  }
  val[u] += x;
}
queue<int> q;
void build() {
  for (int i = (0); i <= (ALP - 1); ++i)
    if (tr[0][i]) q.push(tr[0][i]);
  while (!q.empty()) {
    int u = q.front();
    q.pop();
    val[u] += val[fail[u]];
    for (int i = (0); i <= (ALP - 1); ++i) {
      if (tr[u][i])
        fail[tr[u][i]] = tr[fail[u]][i], q.push(tr[u][i]);
      else
        tr[u][i] = tr[fail[u]][i];
    }
  }
}
char s[N];
int main() {
  scanf("%d", &k);
  for (int i = (1); i <= (k); ++i) {
    int x;
    scanf("%s%d", s, &x);
    insert(s, x);
  }
  build();
  scanf("%s", s + 1);
  int n = strlen(s + 1), cqm = 0;
  for (int i = (1); i <= (n); ++i) cqm += s[i] == '?';
  vector<vector<pair<int, long long> > > Go;
  for (int pos = 0, nex; pos <= n; pos = nex) {
    nex = pos + 1;
    while (nex <= n && s[nex] != '?') ++nex;
    vector<pair<int, long long> > go;
    for (int i = (0); i <= (tot); ++i) {
      int u = i;
      long long v = 0;
      for (int j = (pos + 1); j <= (nex - 1); ++j) {
        u = tr[u][s[j] - 'a'];
        v += val[u];
      }
      go.push_back({u, v});
    }
    assert(int(go.size()) == tot + 1);
    Go.push_back(go);
  }
  long long lim = 1 << ALP;
  const long long INF = 0x3f3f3f3f3f3f3f3f;
  auto *f = F;
  auto *g = G;
  for (int i = (0); i <= (lim - 1); ++i) fill(f[i], f[i] + tot + 1, -INF);
  f[0][0] = 0;
  for (auto p = Go.begin(); p != Go.end(); ++p) {
    for (int i = (0); i <= (lim - 1); ++i) fill(g[i], g[i] + tot + 1, -INF);
    const auto &T = *p;
    for (int j = (0); j <= (tot); ++j) {
      const auto x = T[j];
      for (int i = (0); i <= (lim - 1); ++i) {
        if (f[i][j] == -INF) continue;
        auto &y = g[i][x.first];
        y = max(y, f[i][j] + x.second);
      }
    }
    swap(f, g);
    if ((p + 1) != Go.end()) {
      for (int i = (0); i <= (lim - 1); ++i) fill(g[i], g[i] + tot + 1, -INF);
      for (int i = (0); i <= (lim - 1); ++i) {
        for (int j = (0); j <= (tot); ++j) {
          if (f[i][j] == -INF) continue;
          for (int k = (0); k <= (ALP - 1); ++k)
            if (!(i >> k & 1)) {
              int ni = i ^ (1 << k), nj = tr[j][k];
              g[ni][nj] = max(g[ni][nj], f[i][j] + val[nj]);
            }
        }
      }
      swap(f, g);
    }
  }
  long long ans = -INF;
  for (int i = (0); i <= (lim - 1); ++i)
    for (int j = (0); j <= (tot); ++j) ans = max(ans, f[i][j]);
  printf("%lld\n", ans);
  return 0;
}
