1. 程式人生 > >Best Reward HDU - 3613(manacher)

Best Reward HDU - 3613(manacher)

targe war open spl .net spa 表示 c++ urn

Best Reward

HDU - 3613

題意:每個小寫字母對應有一個價值,給一個小寫字母組成的串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 }
View Code

另解:擴展KMP

Best Reward HDU - 3613(manacher)