#include #include #include #include using namespace __gnu_pbds; using namespace std; #define endl "\n" #define mp make_pair #define st first #define nd second #define pii pair #define pb push_back #define _upgrade ios_base::sync_with_stdio(0), cout.setf(ios::fixed), cout.precision(10), cin.tie(0), cout.tie(0); #define rep(i, n) for (int i = 0; i < (n); ++i) #define fwd(i, a, b) for (int i = (a); i < (b); ++i) #define trav(a, x) for (auto &a : x) #define all(c) (c).begin(), (c).end() #define sz(X) (int)((X).size()) typedef long double ld; typedef unsigned long long ull; typedef long long ll; typedef tree, rb_tree_tag, tree_order_statistics_node_update> indexed_set; // find_by_order(x) <-returns x-th element order_of_key(x) <- returns order of element x // mt19937_64 gen(chrono::steady_clock::now().time_since_epoch().count());uniform_int_distribution distr(0, 1e9);auto my_rand = bind(distr, gen); // my_rand() zwraca teraz liczbe z przedzialu [a, b] #ifdef LOCAL ostream &operator<<(ostream &out, string str) { for (char c : str) out << c; return out; } template ostream &operator<<(ostream &out, pair p) { return out << "(" << p.st << ", " << p.nd << ")"; } template ostream &operator<<(ostream &out, tuple p) { auto &[a, b, c] = p; return out << "(" << a << ", " << b << ", " << c << ")"; } template auto operator<<(ostream &out, T a) -> decltype(a.begin(), out) { out << '{'; for (auto it = a.begin(); it != a.end(); it = next(it)) out << (it != a.begin() ? ", " : "") << *it; return out << '}'; } void dump() { cerr << "\n"; } template void dump(T a, Ts... x) { cerr << a << ", "; dump(x...); } #define debug(...) cerr << "[" #__VA_ARGS__ "]: ", dump(__VA_ARGS__) #else #define debug(...) 42 #endif #define int long long #define QU '?' const int MAXC = 30; const int MAXN = 1e5 + 99; const int MAXL = 20; const int inf = 1e12; int tab[MAXC]; int dp[MAXL][MAXN][MAXC + 1]; string S; int n; int p = -1; void clear() { rep(i, MAXC) tab[i] = -inf; rep(i, MAXL) rep(j, MAXN) rep(k, MAXC + 1) dp[i][j][k] = -inf; } int getidx(char c) { return c - 'A'; } int getbest(int l, int n) { int r = -inf; rep(i, MAXC) r = max(r, dp[l][n][i]); return r; } void f() { rep(i, n) { if (S[i] == QU) rep(j, MAXC) dp[0][i][j] = tab[j]; else dp[0][i][getidx(S[i])] = tab[getidx(S[i])]; dp[0][i][MAXC] = getbest(0, i); debug(dp[0][i][MAXC]); } } void ssset(int t, int i, int d, int ile) { rep(j, MAXC + 1) { dp[t][i][j] = 0; rep(k, p) dp[t][i][j] += dp[t - 1][i + k * d][j]; if (j != MAXC) dp[t][i][j] += ile * tab[j]; if (dp[t][i][j] < 0) dp[t][i][j] = -inf; } dp[t][i][MAXC] = max(dp[t][i][MAXC], getbest(t, i)); debug(t, i, dp[t][i][MAXC]); } int32_t main() { _upgrade; clear(); cin >> n; cin >> S; debug(S, n); int m; cin >> m; rep(j, m) { char c; int x; cin >> c >> x; tab[getidx(c)] = x; } f(); if (n == 1) { cout << dp[0][0][MAXC] << endl; exit(0); } for (int i = 2; i <= n; i++) if (n % i == 0) { p = i; break; } debug(p); n /= p; int ile = p; int t = 1; debug(n, ile, p); while (n > 0) { rep(i, n) ssset(t, i, n, ile); t++; n /= p; ile *= p; } cout << dp[t - 1][0][MAXC] << endl; }