首页 > 代码库 > hdu 3613 Best Reward

hdu 3613 Best Reward

题目:

    链接:Best Reward

题意:

    题目的实质就是,给你字符数组v,字符串s,字符串由a....z组成,v[0]是a的价值,依次类推,,(一定要分的)把s分成两个字符串,若是回文其价值是相应的v[i]的和,不是回文,价值为0。求出最大价值。

算法:

    EKMP算法。EMP算法详解:点击打开链接

思路:

    。。。。。。。。。。。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

char s1[500010],s2[500010];
int sum[500010],next[500010];
int v[30];
int extend1[500010],extend2[500010];

void EKMP(char s[],char t[],int next[],int extend[])//求extend数组的模板
{
    int i,j,p,l;
    int len=strlen(t);
    int len1=strlen(s);
    memset(next,0,sizeof(next));
    memset(extend,0,sizeof(extend));
    next[0]=len;
    j=0;
    while(1+j<len && t[j]==t[1+j])j++;
    next[1]=j;
    int a=1;
    for(i=2; i<len; i++)
    {
        p=next[a]+a-1;
        l=next[i-a];
        if(i+l<p+1)next[i]=l;
        else
        {
            j=max(0,p-i+1);
            while(i+j<len&&t[i+j]==t[0+j])j++;
            next[i]=j;
            a=i;
        }
    }
    j=0;
    while(j<len1&&j<len&&s[j]==t[j])j++;
    extend[0]=j;
    a=0;
    for(i=1; i<len1; i++)
    {
        p=extend[a]+a-1;
        l=next[i-a];
        if(l+i<p+1)extend[i]=next[i-a];
        else
        {
            j=max(0,p-i+1);
            while(i+j<len1&&j<len&&s[i+j]==t[j])j++;
            extend[i]=j;
            a=i;
        }
    }
}

int main()
{
    //freopen("input.txt","r",stdin);
    int t;
    cin>>t;
    while(t--)
    {
        for(int i=0; i<26; i++)
            cin>>v[i];
        getchar();
        gets(s1);
        int len = strlen(s1);
        sum[0] = 0;
        for(int i=0; i<len; i++)
        {
            sum[i+1] = sum[i]+v[s1[i]-‘a‘];//sum[i]表示s1的每个前缀的价值
            s2[i] = s1[len-1-i];//s2是s1的倒置串
        }
        s2[len] = 0;
        EKMP(s2,s1,next,extend1);//s2为子串
        EKMP(s1,s2,next,extend2);//s1为子串
        int ans = -1>>30;
        for(int i=1; i<len; i++)
        {
            int temp = 0;//temp表示所求的价值(回文串在前缀)
            if(i+extend1[i] == len)//相等时,表示构成了回文串
            {
                temp += sum[len-i];//算出相应的价值
            }
            int pos = len-i;//回文串在后缀
            if(pos+extend2[pos] == len)
            {
                temp += sum[len]-sum[pos];
            }
            if(temp>ans)
                ans = temp;
        }
        cout<<ans<<endl;
    }
    return 0;
}