题目:
http://acm.hdu.edu.cn/showproblem.php?pid=3613题意:
最大价值回文串组合,要求把整个字符串拆成两个串,求可能的最大价值和。每个串只有是回文串时才会有价值,价值是这个串中所有字母的价值之和,会给出每个字母的价值。
注意必须分成两个串每个串的长度至少唯一。
思路:
Manacher算法是通过对称位置快速处理回文串的方法,求出一个p[]数组,p[i] 表示第i个字符为中心展开的最大回文串的长度。
依次枚举一遍所有点为第一个子串中心点时可以取得的最大价值,因为 Manacher对原字符串的所有字符之间插入‘#’,所以通过‘#’展开就可以处理偶数串的情况。
代码:
#include <bits/stdc++.h>
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define EPS 1e-6
#define N 1123456
using namespace std;
int n,m,sum,res,flag;
int a[30];
char s[N];
int p[N],f[N];
int Manacher(char *str, int len)
{
int res=0,ans=0;
for(int i=len;i>=0;i--)
{
str[i+i+2] = str[i];
str[i+i+1] = '#';
}
str[0] = '*';
for(int i=2;i<2*len+1;i++)
{
if(p[res]+res > i)
p[i] = min(p[2*res-i],p[res]+res-i);
else
p[i] = 1;
while(str[i-p[i]] == str[i+p[i]])
p[i]++;
if(res+p[res]<i+p[i])res=i;
if(ans<p[i])ans=p[i];
}
return ans-1;
}
int main()
{
int i,j,k,kk,cas,T,t,x,y,z;
scanf("%d",&T);
cas=0;
while(T--)
{
for(i=0;i<26;i++)
scanf("%d",&a[i]);
scanf("%s",s);
n=strlen(s);
Manacher(s,n);
m=strlen(s);
f[0]=0;res=0;
for(i=1;i<m;i++)
f[i]=f[i-1]+(s[i]=='#'?0:a[s[i]-'a']);
for(i=1;i<m;i++)
{
if(i==p[i])
{
x=i+p[i]-1;y=m-1;z=(x+y)/2;
t=f[x];
if(p[z]+z==m)t=f[m-1];
if(x==y)t=0;
res=max(res,t);
}
else if(i+p[i]==m)
t=f[m-1]-f[i-p[i]],res=max(res,t);;
}
printf("%d\n",res);
}
return 0;
}