题意
给你一个字符串要求一刀将字符串一分为2,如果分出来的子串是回文串那么就是权值的和,否则就是0,求最大的价值
思路
manacher求出p[i],然后枚举每个断点,分别判断左右两边是否回文就可以
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN=5e5+10;
int m[30];
char str[MAXN];
char snew[2*MAXN];
int p[2*MAXN];
int psum[2*MAXN];
int init()
{
int len=strlen(str);
snew[0]='$';
snew[1]='#';
int j=2;
for(int i=0;i<len;i++)
{
snew[j++]=str[i];
snew[j++]='#';
}
snew[j]='\0';
return j;
}
int len;
void Manacher()
{
len=init();
int id;
int mx=0;
int maxLen=-1;
for(int i=1;i<len;i++)
{
if(i<mx)
p[i]=min(p[2*id-i],mx-i);
else p[i]=1;
while(snew[i-p[i]]==snew[i+p[i]])
p[i]++;
if(mx<i+p[i])
{
id=i;
mx=i+p[i];
}
maxLen=max(p[i]-1,maxLen);
}
}
int main()
{
int T;cin>>T;
while(T--)
{
for(int i=0;i<26;i++)
scanf("%d",&m[i]);
scanf("%s",str);
Manacher();
psum[0]=psum[1]=0;
for(int i=0;i<len;i++)
{
if(snew[i]=='#'||snew[i]=='$')
psum[i]=psum[i-1];
else psum[i]=m[snew[i]-'a']+psum[i-1];
}
// for(int i=0;i<len;i++)
// cout<<psum[i]<<" ";
// cout<<endl;
int fans=0;
for(int i=3;i<len-2;i+=2)
{
int t1=0;
int t2=0;
int k1=(1+i)/2;
int k2=(i+len-1)/2;
if((k1+p[k1]-1)==i)
t1=psum[i];
if((k2+p[k2])==len)
t2=psum[len-1]-psum[i];
fans=max(fans,t1+t2);
}
cout<<fans<<endl;
}
return 0;
}