Step1 Problem:
Give you the corresponding value of the `a'to `z' characters, and ask you to divide the string into two parts. For each part, if it is a palindrome string, get its value, otherwise 0.
Seek the maximum value of a string divided into two parts.
Step2 Ideas:
Enumeration of segmentation points, O(1) to determine whether the prefix and suffix after segmentation is palindrome string, if yes, O(1) to find value. Take the maximum.
O(1) Whether it is palindrome or not can be used? Extend KMP perhaps manacher Deal with it first.
O(1) Value can be calculated by prefix and pretreatment.
Extend KMP:
next[i]: The longest common prefix length of the suffix string starting at the position I and the original string.
Extend [i]: The longest common prefix length of the suffix string at the beginning of the I position and the other string (that is, the next [] string).
Find all the prefix primitive strings that are palindrome strings (find the next []) of the original strings to match the anti-strings (strings after flipping the original strings)
Find all suffix inverse strings that are palindrome strings (find the next []) of the inverse strings to match the original strings
manacher:
The length of the processed string is len-1, and p[i]-1 represents the length of the I-centered palindrome string.
Step3 Code:
//Extending KMP practices
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+100;
char s[N], fzs[N];
int nex[N], extend[N];
int p[N], sum[N], v[N];
bool qz[N], hz[N];
void get_next(char s[])
{
int len = strlen(s);
int mx = 0, id;
nex[0] = len;
for(int i = 1; i < len; i++)
{
if(i < mx) nex[i] = min(mx-i, nex[i-id]);
else nex[i] = 0;
while(s[nex[i]+i] == s[nex[i]]) nex[i]++;
if(mx < i+nex[i])
{
id = i;
mx = i+nex[i];
}
}
}
void get_extend(char s1[], char s2[])
{
int mx = 0, id;
int len = strlen(s1);
for(int i = 0; i < len; i++)
{
if(i < mx) extend[i] = min(mx-i, nex[i-id]);
else extend[i] = 0;
while(s1[i+extend[i]] == s2[extend[i]] && s2[extend[i]] != '\0') extend[i]++;
if(mx < i+extend[i])
{
id = i;
mx = i+extend[i];
}
}
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
for(int i = 0; i < 26; i++)
scanf("%d", &v[i]);
scanf("%s", s);
int len = strlen(s);
for(int i = 0; i < len; i++)//Seeking string
fzs[len-i-1] = s[i];
fzs[len] = '\0';
memset(qz, 0, sizeof(qz));
memset(hz, 0, sizeof(hz));
get_next(s);//Finding prefix palindrome by inverse string matching
get_extend(fzs, s);
for(int i = 0; i < len; i++)
if(i+extend[i] == len) qz[extend[i]] = 1;//The condition is palindrome string
get_next(fzs);//Inverse String Matches the Original String to Find Suffix Palindromes
get_extend(s, fzs);
for(int i = 0; i < len; i++)
if(i+extend[i] == len) hz[extend[i]] = 1;//The condition is palindrome string
sum[0] = 0;
for(int i = 1; i <= len; i++)//Preprocessing prefixes and note that this starts with 1
sum[i] = sum[i-1] + v[s[i-1]-'a'];
int ans = 0;
for(int i = 1; i < len-1; i++)//Enumeration of the length of partitioned suffixes
{
int tmp = 0;
if(qz[i] == 1) tmp += sum[i];//If the prefix is palindrome
if(hz[len-i] == 1) tmp += sum[len] - sum[i];//If the suffix is palindrome
ans = max(ans, tmp);
}
printf("%d\n", ans);
}
return 0;
}
//manacher approach
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+100;
char sx[N], s[N];
int p[N], sum[N], v[N];
int get_s()
{
int j = 0;
s[j++] = '@'; s[j++] = '#';
int len = strlen(sx);
for(int i = 0; i < len; i++)
{
s[j++] = sx[i];
s[j++] = '#';
}
s[j] = '\0';
return j;
}
void manacher(int len)
{
int mx = 0, id;
for(int i = 1; i < len; i++)
{
if(i < mx) {//At this time, p[i] can be obtained directly, and time optimization can be achieved.
p[i] = min(p[2*id-i], mx - i);
}
else p[i] = 1;
while(s[i-p[i]] == s[i+p[i]]) p[i]++;
if(i+p[i] > mx) {
id = i;
mx = i+p[i];
}
}
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
for(int i = 0; i < 26; i++)
scanf("%d", &v[i]);
scanf("%s", sx);
int len = get_s();
manacher(len);//Find the p[i] array
sum[0] = 0;
for(int i = 1; i < len; i++)//Preprocessing prefix and
{
sum[i] = sum[i-1];
sum[i] += (s[i]=='#') ? 0:v[s[i]-'a'];
}
int ans = 0;
for(int i = 3; i <= len-3; i = i+2)//Enumerate all'"
{
int lpos = (1+i)/2;//Midpoint of prefix
int rpos = (i+len-1)/2;//Midpoint of suffix
int tmp = 0;
if(p[lpos]-1 == (i-1)/2) tmp += sum[i];//If the prefix is palindrome
if(p[rpos]-1 == (len-1-i)/2) tmp += sum[len-1] - sum[i-1];//If the suffix is palindrome
ans = max(ans, tmp);
}
printf("%d\n", ans);
}
return 0;
}