Question:
To give a string S, we need to divide S into two segments T1 and T2. Each letter has a corresponding value. If T1, t2 is the same as a text string (from left to right or from right to left), so they will have a value. This value is the sum of the values of all the letters in the string, if it is not a text string, the value of this string is 0. How much value can be obtained?
Analysis and Summary:
Observe the string S and the string T obtained from S in reverse order:
S: acacac
T: cacaca
If the prefix of S is required, you only need to use the extended KMP algorithm to let S match T and find the common string length of all T suffixes T [I] and S prefix, save it in the extend array and obtain: 0, 5, 0, 3, 0, 1.
Among them, the positions 1, 3, and 5 in extend have public strings, and the matching length must meet the requirements of extend [I] + I = len, len = | S |.
And the prefixes of S are all input strings!
Therefore, we only need to enumerate and scan the extend array once. Before scanning to the current position, it is the first half of T1. Then, based on the extend array, we can determine whether T1 is a text return. What about T2? Just now, we used S to match T. If the suffix is required, we only need T to match S and get an array extend2. Based on extend2, we can determine whether the second half of T2 is a text return.
Code:
[Cpp]
# Include <iostream>
# Include <cstdio>
# Include <cstring>
Using namespace std;
Const int MAXN = 500005;
Char S [MAXN];
Char T [MAXN];
Int f [MAXN];
Int extend1 [MAXN];
Int extend2 [MAXN];
Int val [30];
Int sum [MAXN];
Void revcpy (char * s, char * t, int len ){
Memset (t, 0, sizeof (t ));
For (int I = 0, k = len-1; I <len; ++ I, -- k)
T [I] = s [k];
}
Void getNext (char * T, int * next ){
Int len = strlen (T), a = 0;
Next [0] = len;
While (a <len-1 & T [a] = T [a + 1]) + +;
Next [1] =;
A = 1;
For (int k = 2; k <len; ++ k ){
Int p = a + next [a]-1, L = next [k-a];
If (k + L-1> = p ){
Int j = max (p-k + 1, 0 );
While (k + j <len & T [k + j] = T [j]) ++ j;
Next [k] = j;
A = k;
}
Else
Next [k] = L;
}
}
Void EKMP (char * S, char * T, int * next, int * extend ){
GetNext (T, next );
Int slen = strlen (S), tlen = strlen (T), a = 0;
Int minlen = min (slen, tlen );
While (a <minlen & S [a] = T [a]) ++;
Extend [0] =;
A = 0;
For (int k = 1; k <slen; ++ k ){
Int p = a + extend [a]-1, L = next [k-a];
If (K-1 + L> = p ){
Int j = max (p-k + 1, 0 );
While (k + j <slen & j <tlen & S [k + j] = T [j]) + + j;
Extend [k] = j;
A = k;
}
Else
Extend [k] = L;
}
}
Int main (){
Int nCase;
Scanf ("% d", & nCase );
While (nCase --){
For (int I = 0; I <26; ++ I)
Scanf ("% d", & val [I]);
Scanf ("% s", S );
Memset (sum, 0, sizeof (sum ));
For (int I = 0; S [I]; ++ I ){
Sum [I + 1] = val [S [I]-'a'] + sum [I];
}
Int len = strlen (S );
Revcpy (S, T, strlen (S ));
EKMP (S, T, f, extend2 );
EKMP (T, S, f, extend1 );
Int maxx =-1000000000;
For (int I = 0; I <len; ++ I ){
If (I & extend1 [I] + I = len) {// if the half part is
Int pos = extend1 [I];
Int tmp = sum [pos];
If (extend2 [pos] + pos = len) {// check whether the second half is also a text return.
Tmp + = sum [len]-sum [pos];
}
If (tmp> maxx)
Maxx = tmp;
}
Else {// if the first half is not a text return, check the second half.
Int pos = I + 1, tmp = 0;
If (extend2 [pos] + pos = len ){
Tmp + = sum [len]-sum [pos];
}
If (tmp> maxx)
Maxx = tmp;
}
}
Printf ("% d \ n", maxx );
}
Return 0;
}