【题目链接】
【算法】
正反两遍EXKMP,即可
【代码】
#include<bits/stdc++.h> using namespace std; #define MAXC 26 #define MAXL 500010 int T,ans,tmp,i,len; int a[MAXC+1],Next[MAXL],extend1[MAXL],extend2[MAXL],sum[MAXL]; char s1[MAXL],s2[MAXL]; template <typename T> inline void read(T &x) { int f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) { if (c == '-') f = -f; } for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } template <typename T> inline void write(T x) { if (x < 0) { putchar('-'); x = -x; } if (x > 9) write(x/10); putchar(x%10+'0'); } template <typename T> inline void writeln(T x) { write(x); puts(""); } inline void exkmp(char *s1,char *s2,int *Next,int *Extend) { int i=0,j,pos; while (i + 1 < len && s2[i+1] == s2[i]) i++; Next[1] = i; pos = 1; for (i = 2; i < len; i++) { if (i + Next[i-pos] < pos + Next[pos]) Next[i] = Next[i-pos]; else { j = pos + Next[i-pos] - i; if (j < 0) j = 0; while (i + j < len && s2[j] == s2[i+j]) j++; Next[i] = j; pos = i; } } i = 0; while (i < len && s1[i] == s2[i]) i++; Extend[0] = i; pos = 0; for (i = 1; i < len; i++) { if (i + Next[i-pos] < pos + Extend[pos]) Extend[i] = Next[i-pos]; else { j = pos + Extend[pos] - i; if (j < 0) j = 0; while (i + j < len && s1[i+j] == s2[j]) j++; Extend[i] = j; pos = i; } } } int main() { read(T); while (T--) { for (i = 1; i <= MAXC; i++) read(a[i]); scanf("%s",s1); len = strlen(s1); sum[0] = a[s1[0]-'a'+1]; for (i = 0; i < len; i++) { s2[len-i-1] = s1[i]; if (i > 0) sum[i] = sum[i-1] + a[s1[i]-'a'+1]; } exkmp(s2,s1,Next,extend1); exkmp(s1,s2,Next,extend2); ans = 0; for (i = 0; i < len - 1; i++) { tmp = 0; if (extend1[len-i-1] == i + 1) tmp += sum[i]; if (extend2[i+1] == len - i - 1) tmp += sum[len-1] - sum[i]; ans = max(ans,tmp); } writeln(ans); } return 0; }