码迷,mamicode.com
首页 > 编程语言 > 详细

HDU 3613 Best Reward Manacher算法

时间:2020-02-01 16:34:05      阅读:64      评论:0      收藏:0      [点我收藏+]

标签:它的   pre   实现   detail   n+1   const   war   思路   回文串   

HDU 3613 Best Reward Manacher算法

题意

字符串,需要把这个字符串分成两段,并使得被分开的两段价值和最大。

一个串如果是回文,那么它的价值就是所有字符的价值和,否则价值为0。每个字母都有相应的价值,这个会给出。

解题思路

使用Manacher,我们可以算出每个点的回文串长度,然后我们枚举左半部分的长度(这样很容易算出中心点),进而知道以这个中心点的回文串长度是不是等于这个左半部分的长度。这样来判断。

对于价值,我们可以使用前缀和来提前算好,这样用的话就可以直接用了。下节的代码实现对应这个算法。

搜了一下题解,还有发现使用拓展KMP也可以,思路上也比较简单。
想要看的话可以点击这个链接:https://blog.csdn.net/u013480600/article/details/23041391

代码实现

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=5e5+7;
char str[maxn], s[maxn<<1];
int p[maxn<<1], newlen;
int val[26], presum[maxn];
void init(int n)
{
    newlen=n<<1;
//  s[0]='$';
    for(int i=0; i<=newlen+1; i++) s[i]='#';
    for(int i=1; i<=n; i++) s[i<<1]=str[i];
    s[newlen+2]=0;
}
void manacher()
{
    int mx=0,id=0;
    for(int i=1;i<=newlen;i++)
    {
        if(mx>i) p[i]=min(p[2*id-i],mx-i);
        else p[i]=1;
 
        while(i-p[i]>=0&&s[i-p[i]]==s[i+p[i]]) p[i]++;
        if(i+p[i]>mx) 
        {
            mx=i+p[i];
            id=i;
        }
    }
}
int main()
{
    int t=0;
    scanf("%d",&t);
    while(t--)
    {
        for(int i=0; i<26; i++) scanf("%d", &val[i]);
        scanf("%s", str+1);
        int len=strlen(str+1);
        presum[0]=0;
        for(int i=1; i<=len; i++)
            presum[i] = presum[i-1] + val[ str[i]-'a'];
        init(len);
        manacher();
//      for(int i=1; i<=newlen; i++)
//          printf("%d ", p[i]);
//      printf("\n");
        int ans=-inf;
        for(int cut=1; cut<len; cut++)
        {
            int temp=0;
            int len1=cut, len2=len-len1;
            if(len1%2 == 1)
            {
                int mid=len1/2+1;
                int palen=p[mid<<1]-1; //mid<<1,这里是对应的实际位置 
                if(len1 == palen) temp+=presum[len1]; 
            }
            else 
            {
                int mid=len1/2;
                int palen=p[mid*2+1]-1;
                if(len1 == palen ) temp+=presum[len1];
            }
            if(len2%2==1)
            {
                int mid=len1+len2/2+1;
                int palen=p[mid<<1]-1;
                if(len2 == palen) temp += presum[len] - presum[len1];
            }
            else 
            {
                int mid=len1+len2/2;
                int palen=p[mid*2+1]-1;
                if(len2 == palen ) temp += presum[len] - presum[len1];
            }
            if(temp>ans) ans=temp;
        }
        printf("%d\n", ans);
    }
    return 0;
}

HDU 3613 Best Reward Manacher算法

标签:它的   pre   实现   detail   n+1   const   war   思路   回文串   

原文地址:https://www.cnblogs.com/alking1001/p/12248658.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!