题目:
链接: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;
}