题解: 考虑用ex_kmp维护出当前位置后缀和前缀是否是回文串即可 前缀和统计价值
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define link(x) for(edge *j=h[x];j;j=j->next)
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
const int MAXN=5e5+10;
const double eps=1e-8;
#define ll long long
using namespace std;
struct edge{int t,v;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
void add(int x,int y,int vul){o->t=y;o->v=vul;o->next=h[x];h[x]=o++;}
ll read(){
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-‘0‘,ch=getchar();
return x*f;
}
int key[26],sum[MAXN],nxt[MAXN];
char str[MAXN],s1[MAXN],s2[MAXN];
void ex_next(int ex_Nxt[],char a[]){
int len=strlen(a);
ex_Nxt[0]=len;
int id_max=1;
int t=0;
while(t<len-1&&a[t]==a[t+1]) t++;
ex_Nxt[1]=t;
for(int k=2;k<len;k++){
int p=ex_Nxt[id_max]+id_max-1;int l=ex_Nxt[k-id_max];
if(l+k-1>=p){
int j=(p-k+1)>0?p-k+1:0;
while(j+k<len&&a[j]==a[j+k]) j++;
ex_Nxt[k]=j;
id_max=k;
}
else ex_Nxt[k]=l;
}
return ;
}
void ex_exid(int ex_excd[],int ex_Next[],char a[],char b[]){
int len=strlen(a);
int max_id=0;
int t=0;
int len1=strlen(b);
int len2=min(len1,len);
while(t<len2&&a[t]==b[t]) t++;
ex_excd[0]=t;
for(int i=1;i<len;i++){
int p=ex_excd[max_id]+max_id-1;int l=ex_Next[i-max_id];
if(i+l-1>=p){
int j=(p-i+1)>0?p-i+1:0;
while(j+i<len&&j<len1&&a[j+i]==b[j]) j++;
ex_excd[i]=j;
max_id=i;
}
else ex_excd[i]=l;
}
return ;
}
int c1[MAXN],c2[MAXN];
int main(){
int _=read();
while(_--){
inc(i,0,25)key[i]=read();scanf("%s",str);
int len=strlen(str);
if(len==1){puts("0");continue;}
for(int i=0;i<len;i++)s1[i]=s2[i]=str[i],sum[i+1]=sum[i]+key[(int)(str[i]-‘a‘)];
s1[len]=s2[len]=‘\0‘;
reverse(s2,s2+len);
ex_next(nxt,s2);
ex_exid(c1,nxt,s1,s2);
ex_next(nxt,s1);
ex_exid(c2,nxt,s2,s1);
for(int i=0;i<len;i++){
if(c1[i]==len-i)c1[i]=1;else c1[i]=0;
if(c2[i]==len-i)c2[i]=1;else c2[i]=0;
}
reverse(c2,c2+len);
int maxx=0;
for(int i=1;i<len;i++){
int ans=0;
if(c1[i])ans+=sum[len]-sum[i];
if(c2[i-1])ans+=sum[i];
maxx=max(maxx,ans);
}
printf("%d\n",maxx);
}
}
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 4245 Accepted Submission(s): 1737
原文:https://www.cnblogs.com/wang9897/p/9821271.html