I - ベスト報酬(Manacher +接頭辞配列)

タイトル

苦しい戦いの後、一般的な李は偉大な勝利を獲得しました。今、国家元首は、彼の偉大な悪用のための名誉と宝物をもって彼に報酬を与えることにしました。

これらの宝物の一つは、宝石の26の異なる種類の構成されたネックレスで、ネックレスの長さはNです。(つまり、言うことである:nは宝石は、このネックレスを構成するために一緒に弦楽器、及びこれらの宝石の各々は、唯一の26種に属しています。)

古典ビューに従い、ネックレスは貴重な場合であり、それは回文である場合にのみ - ネックレスはどちらの方向にも同じに見えます。しかし、我々は前述のネックレスは、冒頭に回文ない場合があります。だから、国家元首は、2つの部分にネックレスをカットし、[全般リーにそれらの両方を与えることにしました。

同じ種類のすべての宝石は(あるため、その品質の正または負でもよい - いくつか他の人が普通の石のようなルックスを得る一方、いくつかの種類が美しいです)と同じ値を持っています。回文であるネックレスは、その宝石値との和に等しい値を有します。回文ではないのネックレスは、値ゼロを有しています。

さて問題は、2つのネックレスの値の合計が最大になるように、与えられたネックレスをカットする方法。出力はこの値。
入力
テストケースの数-入力の最初の行は、単一の整数T(1≤T≤10)です。これらのテスト・ケースの説明は次のとおり。

各テストケースのために、最初の行は26個の整数である:V 1、V 2、...、V 26(-100≤VI≤100、1≤I≤26)、各種類の宝石の値を表します。

各テストケースの2行目は「」「Z」のキャラクターから構成される文字列です。ネックレスを表します。異なる宝石の種類を表すキャラクター、及び 'の値はV 1であり、bの値は、V 2、...、などです。文字列の長さは、これ以上500000以下ではありません。

出力
出力単一の整数:一般的なLiはネックレスから得ることができる最大値。
サンプル入力

2
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
ABA
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
acacac

サンプル出力

1
6

説明

TMP Manacherアルゴリズム使用して拡張されたアレイレン各ビット長(パリンドローム2の位置に対応した長さLen-。1)、例えばacacac、LENが3である第三の位置、対応するシーケンスパリンドロームこれはacaca、3の長さであり、 2-1 = 5。Manacherを表す予めPOSを添加する前にI文字列に、まだACACAC使用される(非0の場合)の文字はIパリンドローム配列かどうかを、それぞれ、例えば、[5](acaca)を事前に事前[3 (ACA)1、POS [3](CACである )= 1。すべてのI値のための手段によって得られた配列の要素が1であるか否かを事前とPOS、Manacherレンは、レンされている、であり、IF(I-レン[I] == 0)事前[レン[I ] -1] = 1; IF(I LEN + [I] == LEN + 1)POS [lenの[I] -1] = 1;(Iパリンドローム配列がI] [LENに対応する位置を有する-1文字( #))ここで、添字TMP LENない数は配列の最後のビットである、または元の文字列の長さは、2 + 2 *です。
既知の予めPOSでのみ1から長さ1〜I、Iはプラスに対応する値が存在するか否かをフロントとリア文字長-I文字列のパリンドロームを参照します。そして、文字の数がそれほど存在、NUMレコード・アレイを使用する前の値
であれば(PRE [I])//私判定がパリンドローム配列ではない前に目を
ANS + = [I] NUM; // プラス合計文字I前値
IF(POS [長-I] )// 文字列はパリンドロームではない後の長さ-iが決定される
ANS + =(NUM [長さ] - NUM [I]); // 後者の文字I長-Iを追加での合計値

そして、過去最大の選出ANSを見つける、結果を取得します。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 500010
using namespace std;
int val[27];
char str[maxn];
char tmp[maxn<<1];
int Len[maxn<<1], pre[maxn <<1], pos[maxn <<1], num[maxn];
int length;
void inint(){
    int i;
    tmp[0] = '@';
    for(i = 1; i <= length*2; i += 2){
        tmp[i] ='#';
        tmp[i+1] = str[i/2];
    }
    tmp[length*2+1] = '#';
    tmp[length*2+2] = '$';
}
void Manacher(int len){
    int mx = 0, po = 0, i = 0;
    for(i = 1; i <= len; i++){
        if(i < mx)
            Len[i] = min(Len[2*po-i], mx-i);
        else
            Len[i] = 1;
        while(tmp[i+Len[i]] == tmp[i-Len[i]])
            Len[i]++;
        if(i+Len[i] > mx){
                mx = i+Len[i];
                po = i;
        }
        if(i-Len[i] == 0) pre[Len[i]-1] = 1;
        if(i+Len[i] == len+1) pos[Len[i]-1] = 1;
    }

}
int main(){
    int t, i, j;
    scanf("%d", &t);
    while(t--){
        for(i = 0; i < 26; i++)
            scanf("%d", &val[i]);
        scanf("%s", str);
        length = strlen(str);
        inint();
        num[0] = 0;
        for(i = 1; i <= length; i++)
            num[i] = num[i-1] +val[str[i-1]-'a'];
        memset(pre, 0, sizeof(pre));
        memset(pos, 0, sizeof(pos));
        memset(Len, 0, sizeof(Len));
        Manacher(length*2+1);
        int ans, res = 0;
        for(i = 1; i < length; i++){
            ans = 0;
            if(pre[i]) ans += num[i];
            if(pos[length-i]) ans +=(num[length] - num[i]);
            res = max(ans, res);
        }
        printf("%d\n", res);
    }
    return 0;
}

发布了52 篇原创文章 · 获赞 2 · 访问量 907

おすすめ

転載: blog.csdn.net/qq_44714572/article/details/97287547