Best Reward
题意:每个小写字母对应有一个价值,给一个小写字母组成的串s,现在要把s切割成两段,如果切割后的串是回文串,那么价值就是该段所有字母的价值之和,问总价值最大多少。
用manacher找到前缀回文和后缀回文,枚举切点更新最大之即可。
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int inf=0x3f3f3f3f; 4 const int maxn=500000+10; 5 char s[maxn<<1]; 6 int r[maxn<<1],sum[maxn],val[27]; 7 int per[maxn],pos[maxn];//per标记前i个字符为回文串,pos标记后i个字符为回文串 8 9 int main(){ 10 int T; 11 scanf("%d",&T); 12 while(T--){ 13 for(int i=0;i<26;++i)scanf("%d",&val[i]); 14 scanf("%s",s); 15 int len=strlen(s); 16 sum[0]=val[s[0]-‘a‘]; 17 for(int i=1;i<len;++i) sum[i]=sum[i-1]+val[s[i]-‘a‘]; 18 for(int i=len;i>=0;--i){ 19 s[i+i+2]=s[i]; 20 s[i+i+1]=‘#‘; 21 } 22 s[0]=‘*‘; 23 int id=0; 24 for(int i=2;i<len+len+1;++i){ 25 if(r[id]+id>i) r[i]=min(r[2*id-i],r[id]+id-i); 26 else r[i]=1; 27 while(s[i-r[i]] == s[i+r[i]]) ++r[i]; 28 if(id+r[id]<i+r[i]) id=i; 29 if(i-r[i]==0) per[r[i]-1]=T+1;//表示前缀(前r[i]-1个字符)是回文串 30 if(i+r[i]==len+len+2) pos[r[i]-1]=T+1;//表示后缀(后r[i]-1个字符)是回文串 31 } 32 int ans=0; 33 for(int i=1;i<len;++i){ 34 int temp=0; 35 if(per[i]==T+1) temp+=sum[i-1]; 36 if(pos[len-i]==T+1) temp+=sum[len-1]-sum[i-1]; 37 ans=max(ans,temp); 38 } 39 printf("%d\n",ans); 40 } 41 return 0; 42 }
另解:扩展KMP
时间: 2024-10-12 21:18:32