//
// Created by ll386 on 25-1-16.
//
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 9999;
int f[MAXN][MAXN][2][2]; // 动态规划数组,f[i][j][k][l]表示A序列前i个字符、B序列前j个字符,
// A序列末尾状态为k(0表示空格,1表示字母)、B序列末尾状态为l(0表示空格,1表示字母)时的最大相似度
string a, b; // 存储A和B的DNA序列
int d[4][4]; // 相似度矩阵,d[x][y]表示字符x和y匹配时的相似度
int A, B; // 用于计算连续空格相似度的参数
/*首先,它会检查 c 是否等于 'A'。如果相等,函数将返回 0。这意味着在后续使用这个函数时,如果输入字符是 'A',它会被映射到索引 0。这个索引可以用于访问 d 数组,d[0][y] 可以表示当字符 'A' 与其他字符匹配时的相似度。
接着,如果 c 等于 'T',函数会返回 1。这表示 'T' 被映射到索引 1,可用于访问 d[1][y],表示字符 'T' 与其他字符匹配的相似度。
同样地,当 c 等于 'G' 时,函数返回 2,对应 d[2][y],用于表示字符 'G' 与其他字符的相似度。
最后,如果 c 不是 'A'、'T' 或 'G',那么它必然是 'C'(因为根据题目,序列只包含 A、T、G、C 四种字符),此时函数返回 3,将 'C' 映射到 d[3][y] 来表示它与其他字符的相似度。
这种映射方式使得在后续计算相似度时,可以方便地根据字符获取对应的相似度矩阵中的元素。例如,假设你有两个字符 x 和 y,要查找它们的相似度,可以先使用 charToIndex(x) 和 charToIndex(y) 得到它们的索引,然后使用 d[charToIndex(x)][charToIndex(y)] 来获取相似度。
例如,如果你想查找 'A' 和 'T' 的相似度,调用 charToIndex('A') 得到 0,调用 charToIndex('T') 得到 1,那么 d[charToIndex('A')][charToIndex('T')] 就是 d[0][1],从而得到 'A' 和 'T' 的相似度。*/
int charToIndex(char c) {
if (c == 'A') return 0;
if (c == 'T') return 1;
if (c == 'G') return 2;
return 3;
}
int main() {
cin >> a >> b;
// 读取相似度矩阵
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
cin >> d[i][j];
}
}
cin >> A >> B;
int n = a.length();
int m = b.length();
// 初始化边界条件,当A或B序列为空时的相似度
for (int i = 0; i <= n; ++i) {
for (int j = 0; j <= m; ++j) {
// 当A和B序列都为空时,相似度为0
if (i == 0 && j == 0) {
f[i][j][0][0] = f[i][j][0][1] = f[i][j][1][0] = f[i][j][1][1] = 0;
}
// 当A序列为空,B序列末尾是空格时
else if (i == 0 && j > 0) {
f[i][j][0][0] = f[i][j - 1][0][0] - A - B * (j - 1);
f[i][j][0][1] = f[i][j][0][0];
f[i][j][1][0] = f[i][j][0][0];
f[i][j][1][1] = f[i][j][0][0];
}
// 当A序列为空,B序列末尾是字母时
else if (i == 0 && j > 0) {
f[i][j][0][1] = f[i][j - 1][0][1] - B;
f[i][j][1][0] = f[i][j][0][1];
f[i][j][1][1] = f[i][j][0][1];
}
// 当B序列为空,A序列末尾是空格时
else if (j == 0 && i > 0) {
f[i][j][0][0] = f[i - 1][j][0][0] - A - B * (i - 1);
f[i][j][1][0] = f[i][j][0][0];
f[i][j][0][1] = f[i][j][0][0];
f[i][j][1][1] = f[i][j][0][0];
}
// 当B序列为空,A序列末尾是字母时
else if (j == 0 && i > 0) {
f[i][j][1][0] = f[i - 1][j][1][0] - B;
f[i][j][0][1] = f[i][j][1][0];
f[i][j][1][1] = f[i][j][1][0];
}
}
}
// 动态规划计算最大相似度
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
// 从A末尾是空格,B末尾是字母转移过来
f[i][j][0][1] = max({f[i][j - 1][0][1] - B, f[i][j - 1][1][1] - A, f[i][j - 1][1][0] - A});
// 从A末尾是字母,B末尾是空格转移过来
f[i][j][1][0] = max({f[i - 1][j][1][0] - B, f[i - 1][j][1][1] - A, f[i - 1][j][0][1] - A});
// 从A和B末尾都是字母转移过来
f[i][j][1][1] = max({f[i - 1][j - 1][1][1], f[i - 1][j - 1][1][0], f[i - 1][j - 1][0][1]})
+ d[charToIndex(a[i - 1])][charToIndex(b[j - 1])];
}
}
// 取所有状态中的最大值作为结果
int ans = max({f[n][m][0][0], f[n][m][0][1], f[n][m][1][0], f[n][m][1][1]});
cout << ans << endl;
return 0;
}