也可以做两次EKMP求解
#include <bits/stdc++.h>
using namespace std ;
typedef long long ll ;
const int N = 5e5 + 10 ;
const int INF = 0x3f3f3f3f ;
string s, t;
int len, L[N], R[N] ;
int val[30], sum[N] ;
void init() {
t = "$#" ;
for (int i = 0; i < len; i++) {
t += s[i] ;
t += "#" ;
}
}
void Manacher () {
init();
int len2 = t.size() ;
int p[len2];//以i为中心的回文串的长度+1
int Mx = 0, id = 0;//右边界,id为中心点
for (int i = 1; i < len2; i++) {
if(Mx > i) p[i] = min(p[2 * id - i], Mx - i);
else p[i] = 1 ;
//以i为中心,继续向外拓展
while (t[i + p[i]] == t[i - p[i]]) p[i]++ ;
if (Mx < i + p[i]) {//更新边界,中心点
Mx = i + p[i] ;
id = i ;
}
if (i == p[i] ) L[p[i] - 1] = 1;//以i为中心点可以拓展到字符串最左边,则说明分开以i为中心的左边有回文串,以回文串长度为下标存储即可
if (i + p[i] == len2) R[p[i] - 1] = 1 ;//同理
}
}
int main () {
int T ;
cin >> T ;
while (T--) {
memset(sum, 0, sizeof(sum)) ;
memset(L, 0, sizeof(L)) ;
memset(R, 0, sizeof(R)) ;
for (int i = 0; i < 26; i++)
cin >> val[i] ;
cin >> s ;
len = s.size() ;
sum[0] = 0 ;
for (int i = 1; i <= len; i++)
sum[i] = sum[i - 1] + val[s[i - 1] - 'a'] ;//前缀和
Manacher() ;
int ans = 0 ;
for (int i = 1; i < len; i++) {
int tmp = 0 ;
if (L[i]) tmp += sum[i];//左边回文串长度为i
if (R[len - i]) tmp += sum[len]-sum[i];
ans = max(ans, tmp) ;
}
cout << ans << endl ;
}
return 0;
}