Best Reward HDU - 3613(马拉车+枚举+前缀和)

题意:

  给你一串字符串,每个字符都有一个权值,要求把这个字符串在某点分开,使之成为两个单独的字符串

  如果这两个子串某一个是回文串,则权值为那一个串所有的字符权值和

  若不是回文串,则权值为0

解析:

先用Manacher算法求出以每个字母为中心的回文串的长度,并计算该字符串的前缀价值和。然后枚举切割点,得到两份子串。这样就可以知道每个子串的中心点,然后检查以该子串的中心点作为中心点的回文串的长度,如果长度等于该子串的长度,那么就加上该子串的价值。然后和最优价值比较就行了。

注意只有一个字符时输出0

#include <iostream>
#include <cstdio>
#include <sstream>
#include <cstring>
#include <map>
#include <set>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
#define rap(i, a, n) for(int i=a; i<=n; i++)
#define rep(i, a, n) for(int i=a; i<n; i++)
#define lap(i, a, n) for(int i=n; i>=a; i--)
#define lep(i, a, n) for(int i=n; i>a; i--)
#define rd(a) scanf("%d", &a)
#define rlld(a) scanf("%lld", &a)
#define rc(a) scanf("%c", &a)
#define rs(a) scanf("%s", a)
#define MOD 2018
#define LL long long
#define ULL unsigned long long
#define Pair pair<int, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define _  ios_base::sync_with_stdio(0),cin.tie(0)
//freopen("1.txt", "r", stdin);
using namespace std;
const int maxn = 500010, INF = 0x7fffffff;
char s[maxn], s_new[maxn<<1];
int p[maxn<<1], a[30], sum[maxn];

int init(char *s)
{
    int len = strlen(s);
    s_new[0] = '$';
    s_new[1] = '#';
    int j = 2;
    rep(i, 0, len)
    {
        s_new[j++] = s[i];
        s_new[j++] = '#';
    }
    s_new[j++] = '\0';
   // cout<< strlen(s_new) <<endl;
    return j;
}

void manacher(char *s)
{
    int len = init(s);
 //   int max_len = -1;
    int id, mx = 0;
    rep(i, 1, len)
    {
        if(i < mx)
            p[i] = min(p[2*id-i], mx - i);
        else
            p[i] = 1;
        while(s_new[i-p[i]] == s_new[i+p[i]])
            p[i]++;
        if(mx < i+p[i])
        {
            id = i;
            mx = i+p[i];
        }
    }
}


int T;
int main()
{
    rd(T);
    while(T--)
    {
        rep(i, 0, 26)
            rd(a[i]);
        rs(s);
        if(strlen(s) == 1)
        {
            cout<< "0" <<endl;
            continue;
        }
        sum[0] = a[s[0] - 'a'];
        int len = strlen(s);
        rep(i, 1, len){
            sum[i] = sum[i-1] + a[s[i] - 'a'];
         //   cout<< sum[i] <<endl;
        }
        manacher(s);
        int len2 = strlen(s_new);
        int res = -INF;
        for(int i=3; i<len2 - 2; i+=2)
        {
            int ans = 0;
            if(p[i/2+1] - 1 == i/2) ans += sum[i/2-1];
            if(p[i+(len2-i)/2] - 1 == (len2-i)/2) ans += sum[len-1] - sum[i/2-1];
            res = max(res, ans);
        }
        cout<< res <<endl;
}
return 0; }

 

  

posted @ 2018-08-15 16:29  WTSRUVF  阅读(246)  评论(0编辑  收藏  举报