将模板串s倒置,并尾加到原串后,求得next[]数组,根据next[]数组的性质,便可得前缀的回文串,
同理交原串尾加到倒置串后,便可求得后缀的回文串,然后前缀串和后缀串分开,遍历即可求得最大值!
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 using namespace std; 6 #define N 1000010 7 int v[26], rsum[N/2], lsum[N/2], sum1[N/2], sum2[N/2], next[N]; 8 char s[N/2], s1[N], s2[N]; 9 10 void getfail(char* s, int len){ //next[]数组 11 next[0] = 0; next[1] = 0; 12 for(int i = 1; i < len; ++i){ 13 int j = next[i]; 14 while(j && s[j] != s[i]) j = next[j]; 15 next[i+1] = s[i] == s[j] ? j + 1 : 0; 16 } 17 } 18 19 int main() 20 { 21 int t, i; 22 scanf("%d",&t); 23 while(t--){ 24 for(i = 0; i < 26; ++i) scanf("%d", &v[i]); 25 scanf("%s", s); 26 int len = strlen(s); 27 sum1[0] = v[s[0]-'a']; 28 for(i = 1; i < len; ++i){ 29 sum1[i] = sum1[i-1] + v[s[i]-'a']; 30 } 31 strcpy(s1, s); 32 reverse(s1, s1+len); 33 sum2[0] = v[s1[0]-'a']; 34 for(i = 1; i < len; ++i) 35 sum2[i] = sum2[i-1] + v[s1[i]-'a']; 36 strcpy(s1, s); s1[len] = '!'; //前缀 37 strcpy(s1+len+1, s); 38 reverse(s1+len+1, s1+len+len+1); 39 // cout<<s1<<endl; 40 strcpy(s2, s); s2[len] = '!'; //后缀 41 strcpy(s2+len+1, s); 42 reverse(s2, s2+len); //倒置字符串 43 // cout<<s2<<endl; 44 memset(rsum, 0, sizeof(rsum)); 45 memset(lsum, 0, sizeof(lsum)); 46 getfail(s1, strlen(s1)); 47 i = strlen(s1); 48 do{ 49 i = next[i]; 50 rsum[i] = sum1[i-1]; //前缀成回文串的价值和 51 }while(next[i]); 52 53 getfail(s2, strlen(s2)); 54 55 i = strlen(s2); 56 do{ 57 i = next[i]; 58 lsum[i] = sum2[i-1]; //后缀成回文串的价值和 59 }while(next[i]); 60 int ans = -(1<<30); 61 for(i = 1; i < len; ++i) 62 ans = max(ans, rsum[i] + lsum[len-i]); //遍历求最大值 63 printf("%d ",ans); 64 } 65 return 0; 66 }