HDU-3613 Best Reward (Manacher)

来源:互联网 发布:电脑编程有几种 编辑:程序博客网 时间:2024/04/28 08:07

题目:

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 1123456using 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;}











0 0
原创粉丝点击