// chat gpt's code
#include <bits/stdc++.h>
using namespace std;
using int64 = long long;
static const int64 INF = (1LL << 62);
struct HashPair {
uint64_t h1, h2;
bool operator<(const HashPair& other) const {
if (h1 != other.h1) return h1 < other.h1;
return h2 < other.h2;
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N;
string S;
int64 A, B, C;
cin >> N >> S >> A >> B >> C;
S = " " + S; // 1-indexed
// Double rolling hash.
const uint64_t M1 = 1000000007ULL;
const uint64_t M2 = 1000000009ULL;
const uint64_t BASE = 911382323ULL;
vector<uint64_t> p1(N + 1), p2(N + 1), pw1(N + 1), pw2(N + 1);
pw1[0] = pw2[0] = 1;
for (int i = 1; i <= N; ++i) {
pw1[i] = (pw1[i - 1] * BASE) % M1;
pw2[i] = (pw2[i - 1] * BASE) % M2;
}
for (int i = 1; i <= N; ++i) {
uint64_t x = (uint64_t)(S[i] - 'a' + 1);
p1[i] = (p1[i - 1] * BASE + x) % M1;
p2[i] = (p2[i - 1] * BASE + x) % M2;
}
auto get_hash = [&](int l, int r) -> HashPair {
uint64_t x1 = (p1[r] + M1 - (p1[l - 1] * pw1[r - l + 1]) % M1) % M1;
uint64_t x2 = (p2[r] + M2 - (p2[l - 1] * pw2[r - l + 1]) % M2) % M2;
return {x1, x2};
};
vector<vector<int64>> dp(N + 2, vector<int64>(N + 2, INF));
for (int i = 1; i <= N; ++i) dp[i][i] = A;
for (int len = 1; len <= N; ++len) {
// next[pos] = earliest non-overlapping next occurrence of S[pos..pos+len-1]
vector<pair<HashPair, int>> v;
v.reserve(N - len + 1);
for (int i = 1; i + len - 1 <= N; ++i) {
v.push_back({get_hash(i, i + len - 1), i});
}
sort(v.begin(), v.end(), [](const auto& a, const auto& b) {
if (a.first < b.first) return true;
if (b.first < a.first) return false;
return a.second < b.second;
});
vector<int> nxt(N + 2, -1);
for (int i = 0; i < (int)v.size();) {
int j = i;
while (j < (int)v.size() &&
!(v[i].first < v[j].first) &&
!(v[j].first < v[i].first)) {
++j;
}
// positions v[i..j-1] share the same substring
int ptr = i + 1;
for (int t = i; t < j; ++t) {
int pos = v[t].second;
if (ptr < t + 1) ptr = t + 1;
while (ptr < j && v[ptr].second < pos + len) ++ptr;
if (ptr < j) nxt[pos] = v[ptr].second;
}
i = j;
}
for (int l = 1; l + len - 1 <= N; ++l) {
int r = l + len - 1;
int64 cur = dp[l][r];
if (cur >= INF) continue;
// Type one character to either side.
if (r + 1 <= N) dp[l][r + 1] = min(dp[l][r + 1], cur + A);
if (l - 1 >= 1) dp[l - 1][r] = min(dp[l - 1][r], cur + A);
// Copy-paste chain for this exact substring length.
if (nxt[l] == -1) continue;
int64 cost = cur + B + C; // cut, then first paste
int curEnd = r;
int p = nxt[l];
while (p != -1) {
// Type the gap between consecutive occurrences, then paste once more.
cost += (int64)(p - curEnd - 1) * A + C;
curEnd = p + len - 1;
if (curEnd > N) break;
dp[l][curEnd] = min(dp[l][curEnd], cost);
p = nxt[p];
}
}
}
cout << dp[1][N] << '\n';
return 0;
}