题目:
链接:Best Reward
题意:
题目的实质就是,给你字符数组v,字符串s,字符串由a....z组成,v[0]是a的价值,依次类推,,(一定要分的)把s分成两个字符串,若是回文其价值是相应的v[i]的和,不是回文,价值为0。求出最大价值。
算法:
EKMP算法。EMP算法详解:点击打开链接
思路:
。。。。。。。。。。。
代码:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; char s1[500010],s2[500010]; int sum[500010],next[500010]; int v[30]; int extend1[500010],extend2[500010]; void EKMP(char s[],char t[],int next[],int extend[])//求extend数组的模板 { int i,j,p,l; int len=strlen(t); int len1=strlen(s); memset(next,0,sizeof(next)); memset(extend,0,sizeof(extend)); next[0]=len; j=0; while(1+j<len && t[j]==t[1+j])j++; next[1]=j; int a=1; for(i=2; i<len; i++) { p=next[a]+a-1; l=next[i-a]; if(i+l<p+1)next[i]=l; else { j=max(0,p-i+1); while(i+j<len&&t[i+j]==t[0+j])j++; next[i]=j; a=i; } } j=0; while(j<len1&&j<len&&s[j]==t[j])j++; extend[0]=j; a=0; for(i=1; i<len1; i++) { p=extend[a]+a-1; l=next[i-a]; if(l+i<p+1)extend[i]=next[i-a]; else { j=max(0,p-i+1); while(i+j<len1&&j<len&&s[i+j]==t[j])j++; extend[i]=j; a=i; } } } int main() { //freopen("input.txt","r",stdin); int t; cin>>t; while(t--) { for(int i=0; i<26; i++) cin>>v[i]; getchar(); gets(s1); int len = strlen(s1); sum[0] = 0; for(int i=0; i<len; i++) { sum[i+1] = sum[i]+v[s1[i]-‘a‘];//sum[i]表示s1的每个前缀的价值 s2[i] = s1[len-1-i];//s2是s1的倒置串 } s2[len] = 0; EKMP(s2,s1,next,extend1);//s2为子串 EKMP(s1,s2,next,extend2);//s1为子串 int ans = -1>>30; for(int i=1; i<len; i++) { int temp = 0;//temp表示所求的价值(回文串在前缀) if(i+extend1[i] == len)//相等时,表示构成了回文串 { temp += sum[len-i];//算出相应的价值 } int pos = len-i;//回文串在后缀 if(pos+extend2[pos] == len) { temp += sum[len]-sum[pos]; } if(temp>ans) ans = temp; } cout<<ans<<endl; } return 0; }
hdu 3613 Best Reward,布布扣,bubuko.com
原文:http://blog.csdn.net/u013147615/article/details/25342027