#include <bits/stdc++.h>
using namespace std;
const long long INF = 1e18;
const int M = 14;
struct Tree {
  int ch[M];
  int fail;
  int val;
} T[1010];
int tot;
void insert(char* str, int len, int val) {
  int now = 0;
  for (int i = 0; i < len; i++) {
    int c = str[i] - 'a';
    if (!T[now].ch[c]) T[now].ch[c] = ++tot;
    now = T[now].ch[c];
  }
  T[now].val += val;
  return;
}
void AC_build() {
  queue<int> q;
  for (int i = 0; i < M; i++)
    if (T[0].ch[i]) q.push(T[0].ch[i]);
  while (!q.empty()) {
    int u = q.front();
    q.pop();
    for (int i = 0; i < M; i++)
      if (T[u].ch[i]) {
        int v = T[u].ch[i];
        T[v].fail = T[T[u].fail].ch[i];
        q.push(v);
      } else
        T[u].ch[i] = T[T[u].fail].ch[i];
    T[u].val += T[T[u].fail].val;
  }
  return;
}
inline pair<int, int> work(int u, int c) {
  u = T[u].ch[c];
  return make_pair(u, T[u].val);
}
char S[400010];
char str[1010];
pair<int, long long> work(int u, int l, int r) {
  long long sum = 0;
  for (int i = l; i <= r; i++) {
    pair<int, int> pr = work(u, S[i] - 'a');
    sum += pr.second;
    u = pr.first;
  }
  return make_pair(u, sum);
}
long long f[1 << M][1010];
inline void qmax(long long& x, long long y) {
  if (x < y) x = y;
  return;
}
int siz[1 << M];
void solve1(int x) {
  for (int s = 0; s < (1 << M); s++) {
    if (siz[s] != x) continue;
    for (int u = 0; u <= tot; u++) {
      if (f[s][u] == -INF) continue;
      for (int c = 0; c < M; c++) {
        if (s & (1 << c)) continue;
        pair<int, int> pr = work(u, c);
        int v = pr.first, val = pr.second;
        qmax(f[s | (1 << c)][v], f[s][u] + val);
      }
    }
  }
  return;
}
pair<int, long long> Pr[1010];
long long g[1010];
void solve2(int l, int r, int x) {
  for (int u = 0; u <= tot; u++) Pr[u] = work(u, l, r);
  for (int s = 0; s < (1 << M); s++)
    if (siz[s] == x) {
      for (int u = 0; u <= tot; u++) g[u] = -INF;
      for (int u = 0; u <= tot; u++)
        qmax(g[Pr[u].first], f[s][u] + Pr[u].second);
      for (int u = 0; u <= tot; u++) f[s][u] = g[u];
    }
  return;
}
int pos[21];
int main() {
  for (int i = 1; i < (1 << M); i++) siz[i] = siz[i >> 1] + (i & 1);
  int k;
  scanf("%d", &k);
  for (int i = 1; i <= k; i++) {
    int val, len;
    scanf("%s %d", str, &val);
    len = strlen(str);
    insert(str, len, val);
  }
  AC_build();
  scanf("%s", S + 1);
  int n = strlen(S + 1);
  int N = 0;
  pos[0] = 0;
  for (int i = 1; i <= n; i++)
    if (S[i] == '?') pos[++N] = i;
  for (int s = 0; s < (1 << M); s++)
    for (int u = 0; u <= tot; u++) f[s][u] = -INF;
  f[0][0] = 0;
  for (int i = 1; i <= N; i++) {
    solve2(pos[i - 1] + 1, pos[i] - 1, i - 1);
    solve1(i - 1);
  }
  solve2(pos[N] + 1, n, N);
  long long ans = -INF;
  for (int s = 0; s < (1 << M); s++)
    for (int u = 0; u <= tot; u++)
      if (siz[s] == N) qmax(ans, f[s][u]);
  printf("%I64d\n", ans);
  return 0;
}
