#include <bits/stdc++.h>
using namespace std;
bool home = 1;
signed realMain();
signed main() {
  home = 0;
  if (home) {
    freopen("input", "r", stdin);
  } else {
    ios::sync_with_stdio(0);
    cin.tie(0);
  }
  realMain();
}
const long long N = 1000 + 7;
long long n, cost[N], y;
string s, v[N];
struct node {
  node* k[14];
  node* to;
  string val;
  long long cost;
  long long id;
  node() {
    id = 0;
    val = "";
    for (long long j = 0; j < 14; j++) {
      k[j] = 0;
    }
    cost = 0;
    to = 0;
  }
};
node* root = new node;
vector<node*> ord;
void bfs() {
  queue<node*> q;
  q.push(root);
  while (!q.empty()) {
    node* now = q.front();
    ord.push_back(now);
    q.pop();
    for (long long j = 0; j < 14; j++) {
      if (now->k[j]) {
        q.push(now->k[j]);
      }
    }
  }
}
void build() {
  root->id = ++y;
  for (long long i = 1; i <= n; i++) {
    node* now = root;
    for (auto& ch : v[i]) {
      long long x = ch - 'a';
      if (!now->k[x]) {
        now->k[x] = new node;
        now->k[x]->id = ++y;
        now->k[x]->val = now->val + ch;
      }
      now = now->k[x];
    }
    now->cost += cost[i];
  }
  bfs();
  root->to = root;
  for (auto& now : ord) {
    for (long long j = 0; j < 14; j++) {
      if (now->k[j]) {
        node* sol = now->to;
        while (sol != root && !sol->k[j]) {
          sol = sol->to;
        }
        if (now != root && sol->k[j]) {
          sol = sol->k[j];
        }
        now->k[j]->to = sol;
      }
    }
  }
  for (auto& now : ord) {
    now->cost += now->to->cost;
  }
}
const long long K = 14;
const long long INF = (long long)1e18;
long long urm[N][K], gain[N];
string what[N];
long long after_state[K + 7][N], after_gain[K + 7][N];
long long dp[1 << K][N];
signed realMain() {
  cin >> n;
  for (long long i = 1; i <= n; i++) {
    cin >> v[i] >> cost[i];
  }
  cin >> s;
  build();
  for (auto& now : ord) {
    what[now->id] = now->val;
    gain[now->id] = now->cost;
    for (long long j = 0; j < 14; j++) {
      node* ret = now;
      while (ret != root && !ret->k[j]) {
        ret = ret->to;
      }
      if (ret->k[j]) {
        ret = ret->k[j];
      }
      urm[now->id][j] = ret->id;
    }
  }
  long long sz = (long long)s.size(), qs = 0;
  vector<long long> questions = {-1};
  for (long long j = 0; j < sz; j++) {
    if (s[j] == '?') {
      qs++;
      questions.push_back(j);
    }
  }
  questions.push_back(sz);
  for (long long j = 0; j + 1 < (long long)questions.size(); j++) {
    long long l = questions[j] + 1, r = questions[j + 1] - 1;
    for (long long state = 1; state <= y; state++) {
      long long now_state = state, now_gain = 0;
      for (long long j = l; j <= r; j++) {
        now_state = urm[now_state][s[j] - 'a'];
        now_gain += gain[now_state];
      }
      after_state[j][state] = now_state;
      after_gain[j][state] = now_gain;
    }
  }
  for (long long mask = 0; mask < (1 << K); mask++) {
    for (long long i = 1; i <= y; i++) {
      dp[mask][i] = -INF;
    }
  }
  dp[0][1] = 0;
  long long ret = -INF;
  for (long long mask = 0; mask < (1 << K); mask++) {
    for (long long i = 1; i <= y; i++) {
      if (dp[mask][i] == -INF) continue;
      long long cnt = 0;
      for (long long bit = 0; bit < K; bit++) {
        if (mask & (1 << bit)) {
          cnt++;
        }
      }
      if (cnt == qs) {
        long long relax = dp[mask][i] + after_gain[cnt][i];
        ret = max(ret, relax);
        continue;
      }
      assert(cnt < qs);
      for (long long bit = 0; bit < K; bit++) {
        if (!(mask & (1 << bit))) {
          long long new_mask = mask + (1 << bit);
          long long state = urm[after_state[cnt][i]][bit];
          long long relax = dp[mask][i] + after_gain[cnt][i] + gain[state];
          dp[new_mask][state] = max(dp[new_mask][state], relax);
        }
      }
    }
  }
  cout << ret << "\n";
  return 0;
}
