HDU 3613 Best Reward Manacher算法

Posted alking1001

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 3613 Best Reward Manacher算法相关的知识,希望对你有一定的参考价值。

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("
");
        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
", ans);
    }
    return 0;
}

以上是关于HDU 3613 Best Reward Manacher算法的主要内容,如果未能解决你的问题,请参考以下文章

HDU 3613 Best Reward(拓展KMP算法求解)

HDU3613 Best Reward

hdu3613 Best Reward

hdu 3613 Best Reward (manachar算法)

Best Reward HDU - 3613(manacher)

hdu3613Best Reward