#include <bits/stdc++.h>
using namespace std;
const int MOD = 998244353;
int K;
vector<string> T;
vector<long long> C;
string S;
vector<vector<vector<pair<int, int>>>> TR;
vector<vector<long long>> SC;
vector<vector<int>> F;
void getPrefix(int n) {
  int c = 0;
  string &b = T[n];
  vector<int> f(b.size() + 1, -1);
  for (int i = 1; i < b.size(); i++) {
    if (b[c] == b[i]) {
      f[i] = f[c];
    } else {
      f[i] = c;
      while (c >= 0 && b[c] != b[i]) {
        c = f[c];
      }
    }
    c++;
  }
  f[b.size()] = c;
  F[n] = f;
}
void cacTR(int n) {
  TR[n].assign(T[n].size() + 1, vector<pair<int, int>>(14, {0, 0}));
  for (int j = 0; j < K; j++) {
    int q = 0;
    for (int i = 0; i <= T[n].size(); i++) {
      if (i > 0) {
        char c = T[n][i - 1];
        while (q >= 0 && c != T[j][q]) q = F[j][q];
        q++;
      }
      for (char c = 'a'; c <= 'n'; c++) {
        int p = q;
        while (p >= 0 && c != T[j][p]) {
          p = F[j][p];
        }
        p++;
        if (TR[n][i][c - 'a'].second < p) {
          TR[n][i][c - 'a'] = {j, p};
        }
      }
    }
  }
}
void solve() {
  cin >> K;
  T.resize(K);
  C.resize(K);
  for (int i = 0; i < K; i++) {
    cin >> T[i];
    cin >> C[i];
  }
  cin >> S;
  TR.resize(K);
  SC.resize(K);
  F.resize(K);
  for (int i = 0; i < K; i++) {
    getPrefix(i);
    SC[i].assign(T[i].size() + 1, 0);
    for (int j = 0; j <= T[i].size(); j++) {
      for (int k = 0; k < K; k++) {
        if (j >= T[k].size() &&
            T[i].compare(j - T[k].size(), T[k].size(), T[k]) == 0)
          SC[i][j] += C[k];
      }
    }
  }
  for (int i = 0; i < K; i++) {
    cacTR(i);
  }
  map<tuple<int, int>, map<int, long long>> mm;
  mm[{0, 0}] = {{0, 0}};
  long long add = 0;
  for (int i = 0; i < S.size(); i++) {
    int na, nb, nc;
    int a, b, c;
    long long score;
    long long ns;
    map<tuple<int, int>, map<int, long long>> newmm;
    if (S[i] != '?' && mm.size() == 1) {
      tie(a, b) = mm.begin()->first;
      tie(na, nb) = TR[a][b][S[i] - 'a'];
      add += SC[na][nb];
      newmm[{na, nb}] = move(mm[{a, b}]);
      swap(mm, newmm);
      continue;
    }
    for (auto p : mm) {
      tie(a, b) = p.first;
      for (auto q : p.second) {
        tie(c, score) = q;
        if (S[i] == '?') {
          for (int j = 0; j < 14; j++) {
            if ((1 << j) & c) continue;
            int nc = (1 << j) | c;
            tie(na, nb) = TR[a][b][j];
            ns = score + SC[na][nb];
            if (newmm.find({na, nb}) == newmm.end() ||
                newmm[{na, nb}].find(nc) == newmm[{na, nb}].end() ||
                newmm[{na, nb}][nc] < ns)
              newmm[{na, nb}][nc] = ns;
          }
        } else {
          tie(na, nb) = TR[a][b][S[i] - 'a'];
          ns = score + SC[na][nb];
          nc = c;
          auto key = make_tuple(na, nb, nc);
          if (newmm.find({na, nb}) == newmm.end() ||
              newmm[{na, nb}].find(nc) == newmm[{na, nb}].end() ||
              newmm[{na, nb}][nc] < ns)
            newmm[{na, nb}][nc] = ns;
        }
      }
    }
    swap(mm, newmm);
  }
  long long ans = LLONG_MIN;
  for (auto p : mm)
    for (auto q : p.second) ans = max(ans, q.second);
  cout << ans + add << endl;
}
int main() {
  std::ios::sync_with_stdio(false);
  cin.tie(NULL);
  cout.precision(10);
  int T = 1;
  for (int i = 1; i <= T; i++) {
    solve();
  }
  return 0;
}
