KMP hdu-3613-Best Reward

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=3613

题目意思:

a-z每个字母有一个值,给个字符串,让你分成两部分,每一部分至少有一个字符。

如果该串是回文字符串,则该值为所有字符的值之和,如果不是字符串,则为0.

让你计算怎样分割使得两部分的总和值最大。

解题思路:

利用回文字符串的next[i]也是回文字符串的特点,求出串中所有的回文串。

然后倒过来,求出后缀的会问字符串。

然后一次遍历就可以求出最大的值。

代码:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<stack>
#include<list>
#include<queue>
#define eps 1e-6
#define INF (1<<30)
#define PI acos(-1.0)
using namespace std;

#define Maxn 510000

int value[27],sum[2][Maxn]; //分别表示从前至后的回文串的值和从后到前的回文串的值
int ss[2][Maxn],next[Maxn*2]; //从前之后求出各值
char save[Maxn];
char stemp[Maxn*2];

void getnext(char * a,int len)
{
   int j=0;

   next[1]=0;
   for(int i=2;i<=len;i++)
   {
      while(j>0&&a[j+1]-a[i])
         j=next[j];
      if(a[j+1]==a[i])
         j++;
      next[i]=j;
   }
   return ;
}

int main()
{
   int t;

   scanf("%d",&t);
   while(t--)
   {
      for(int i=1;i<=26;i++)
         scanf("%d",&value[i]);
      scanf("%s",save+1);
      int len=strlen(save+1);
      memset(ss,0,sizeof(ss));
      for(int i=1;i<=len;i++) //预处理出所有的前缀值的和
         ss[0][i]=ss[0][i-1]+value[save[i]-'a'+1];
      for(int i=len;i>=1;i--) //预处理出所有的后缀值的和
         ss[1][len-i+1]=ss[1][len-i]+value[save[i]-'a'+1];

      strcpy(stemp+1,save+1);
      stemp[len+1]='*';
      strcpy(stemp+len+2,save+1);
     // printf("%s\n",stemp+1);
      std::reverse(stemp+len+2,stemp+len+len+2); //翻转
      //printf("%s\n",stemp+1);
      getnext(stemp,len+len+1);
      memset(sum,0,sizeof(sum));
      int i=len+len+1;
      do //是回文串,注意只有一个元素也是回文串
      {
         i=next[i];
        // printf("i:%d next[i]:%d\n",i,next[i]);
         sum[0][i]=ss[0][i];

      }while(next[i]);

      //倒过来再求一遍
      //printf("sum[0][1]:%d\n",sum[0][1]);
      std::reverse(stemp+1,stemp+len+1);
      std::reverse(stemp+len+2,stemp+len+len+2);
      getnext(stemp,len+len+1);
      i=len+len+1;
      do
      {
         i=next[i];
         sum[1][i]=ss[1][i];
      }while(next[i]);
      int ans=-INF;
      for(int i=1;i<len;i++)
         ans=max(ans,sum[0][i]+sum[1][len-i]);
      printf("%d\n",ans);
   }
   return 0;
}







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值