/**
题目:hdu3613 Best Reward
链接:http://acm.hdu.edu.cn/showproblem.php?pid=3613题意:有一个字符串,把他切成两部分。
如果这部分是回文串,那么他的值为所有字母的权值和。否则这部分值为0;这两部分的值和为该切法的权值。
求最大的切法的权值。
思路:
如果能够判断[0,i],[i,n-1]是一个回文串(0<=i
取最大的。
扩展kmp的做法。
先计算l[i]=1,表示[0,i]是一个回文串;那么[0,k1]与[k2,i]相等。0是固定的。
获得原串t的反转串s。求extend[i],表示s串从[i,n-1]与原串t的最长公共前缀。
枚举s串的i。那么从[i,n-1]的长度n-i;如果extend[i]*2+1>=n-i那么表示原串t中的[0,n-1-i]是一个回文串即l[n-1-i] = 1;
现在求r[i]=1,表示[i,n-1]是一个回文串;那么[i,k1]与[k2,n-1]相等。n-1是固定的。
求extend[i],表示t串从[i,n-1]与s串的最长公共前缀。
枚举t串的i。那么从[i,n-1]的长度为n-i;如果extend[i]*2+1>=n-i那么表示原串[i,n-1]是一个回文串即r[i] = 1;*/#include#include#include#include#include#include
using namespacestd;const int INF = 0x3f3f3f3f;const int maxn = 5e5+10;chars[maxn], t[maxn];intf[maxn], Next[maxn], extend[maxn];int sum[maxn], w[30];int l[maxn], r[maxn];///l[i]=1表示[0,i]是一个回文串.r[i]=1表示[i,n-1]是一个回文串。
void GetNext(char *T,int*next)
{int a=0;int Tlen=strlen(T);
next[0]=Tlen;while(a
next[1]=a;
a=1;for(int k=2;k
{int p=a+next[a]-1,L=next[k-a];if((k-1)+L>=p)
{int j=(p-k+1)>0? p-k+1:0;while(k+j
next[k]=j;
a=k;
}else next[k]=L;
}
}void GetExtend(char *S,char *T,int* next,int*extend)
{int a=0;
GetNext(T,next);int Slen=strlen(S);int Tlen=strlen(T);int MinLen=Slen
extend[0]=a;
a=0;for(int k=1;k
{int p=a+extend[a]-1,L=next[k-a];if((k-1)+L>=p)
{int j=(p-k+1)>0? p-k+1:0;while(k+j
extend[k]=j;
a=k;
}else extend[k]=L;
}
}void getlr(int* extend,int *l,int flag,intn)
{intlen;for(int i = 0; i < n; i++){
len= n-i;if(extend[i]*2+1>=len){if(flag) l[i] = 1;else l[n-1-i] = 1;
}
}
}void test(int *f,intn)
{for(int i = 0; i < n; i++){
printf("f[%d] = %d\n",i,f[i]);
}
}intmain()
{//freopen("in.txt","r",stdin);
intT;
cin>>T;while(T--){for(int i = 0; i < 26; i++) scanf("%d",&w[i]);
scanf("%s",t);int n =strlen(t);for(int i = 0; i < n; i++) s[n-1-i] =t[i];
s[n]= '\0';
sum[0] = w[t[0]-'a'];for(int i = 1; i < n; i++){
sum[i]= sum[i-1]+w[t[i]-'a'];
}
memset(l,0, sizeofl);
memset(r,0, sizeofr);
GetExtend(s,t,Next,extend);
getlr(extend,l,0,n);
GetExtend(t,s,Next,extend);
getlr(extend,r,1,n);int ans = -INF, ansa, ansb;for(int i = 1; i < n; i++){if(l[i-1]){
ansa= sum[i-1];
}else ansa = 0;if(r[i]){
ansb= sum[n-1]-sum[i-1];
}else ansb = 0;
ans= max(ans,ansa+ansb);
}
printf("%d\n",ans);
}return 0;
}