题目链接:https://vjudge.net/problem/HDU-3613

Best Reward

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 3104    Accepted Submission(s): 1277

Problem Description
After an uphill battle, General Li won a great victory. Now the head of state decide to reward him with honor and treasures for his great exploit.

One of these treasures is a necklace made up of 26 different kinds of gemstones, and the length of the necklace is n. (That is to say: n gemstones are stringed together to constitute this necklace, and each of these gemstones belongs to only one of the 26 kinds.)

In accordance with the classical view, a necklace is valuable if and only if it is a palindrome - the necklace looks the same in either direction. However, the necklace we mentioned above may not a palindrome at the beginning. So the head of state decide to cut the necklace into two part, and then give both of them to General Li.

All gemstones of the same kind has the same value (may be positive or negative because of their quality - some kinds are beautiful while some others may looks just like normal stones). A necklace that is palindrom has value equal to the sum of its gemstones' value. while a necklace that is not palindrom has value zero.

Now the problem is: how to cut the given necklace so that the sum of the two necklaces's value is greatest. Output this value.

 
Input
The first line of input is a single integer T (1 ≤ T ≤ 10) - the number of test cases. The description of these test cases follows.

For each test case, the first line is 26 integers: v1, v2, ..., v26 (-100 ≤ vi ≤ 100, 1 ≤ i ≤ 26), represent the value of gemstones of each kind.

The second line of each test case is a string made up of charactor 'a' to 'z'. representing the necklace. Different charactor representing different kinds of gemstones, and the value of 'a' is v1, the value of 'b' is v2, ..., and so on. The length of the string is no more than 500000.

 
Output
Output a single Integer: the maximum value General Li can get from the necklace.
 
Sample Input
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
 
Sample Output
1
6
 
Source
 
Recommend
lcy

题解:

1.求出字符串值的前缀和以及后缀和。

2.用Manacher算法或者扩展KMP算法求出:每个前缀和每个后缀是否为回文串。

3.枚举分分割位置,然后再根据左右段字符串是否为回文串来进行求值。

4.Manacher算法的认识在处理的时候,如果以“#”为中点,那么实际的回文串长度为偶数;如果以输入的字符为中点,那么实际的回文串长度为奇数。

Manacher:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <sstream>
#include <algorithm>
using namespace std;
typedef long long LL;
const double eps = 1e-;
const int INF = 2e9;
const LL LNF = 9e18;
const int MAXN = 5e5+; char s[MAXN];
int val[], pre[MAXN], suf[MAXN];
int sum[MAXN][]; int Ma[MAXN<<], Mp[MAXN<<];
void Manacher(char *s, int len)
{
int l = ;
Ma[l++] = '$'; Ma[l++] = '#';
for(int i = ; i<len; i++)
{
Ma[l++] = s[i];
Ma[l++] = '#';
}
Ma[l] = ; int mx = , id = ;
for(int i = ; i<l; i++)
{
Mp[i] = mx>=i?min(Mp[*id-i], mx-i):;
while(Ma[i-Mp[i]-]==Ma[i+Mp[i]+]) Mp[i]++;
if(i+Mp[i]>mx)
{
mx = i+Mp[i];
id = i;
} //记录以s[i/2-1]为中点(长度为奇时,为中点;长度为偶时,为左半段的末点)时的最长回文串
//如果处理的时候,以“#”为中点,那么实际的长度为偶数
//如果处理的时候,以输入的字符为中点,那么实际的长度为奇数
if(i>=) sum[i/-][Ma[i]!='#'] = Mp[i];
}
} int main()
{
int T;
scanf("%d", &T);
while(T--)
{
for(int i = ; i<; i++)
scanf("%d", &val[i]); scanf("%s", s);
int len = strlen(s);
pre[] = val[s[]-'a'];
suf[len-] = val[s[len-]-'a'];
for(int i = ; i<len; i++)
{
pre[i] = pre[i-] + val[s[i]-'a']; //求前缀和
suf[len-i-] = suf[len-i] + val[s[len-i-]-'a']; //求后缀和
} memset(sum, , sizeof(sum));
Manacher(s, len); int ans = -INF;
for(int i = ; i<=len-; i++)
{
int Lmid = i/, Rmid = (i++len-)/; //找到左右两段的中点
int Llen = i+, Rlen = len-Llen; //求出左右两段的长度 int tmp = ;
if(sum[Lmid][Llen%]==Llen) tmp += pre[i]; //如果左段为回文串
if(sum[Rmid][Rlen%]==Rlen) tmp += suf[i+]; //如果右段为回文串
ans = max(ans, tmp);
}
printf("%d\n", ans);
}
}

扩展KMP:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <sstream>
#include <algorithm>
using namespace std;
typedef long long LL;
const double EPS = 1e-;
const int INF = 2e9;
const LL LNF = 9e18;
const int MOD = 1e9+;
const int MAXN = 5e5+; void pre_EXKMP(char x[], int m, int Next[])
{
Next[] = m;
int j = ;
while(j+<m && x[+j]==x[+j]) j++;
Next[] = j;
int k = ;
for(int i = ; i<m; i++)
{
int p = Next[k]+k-;
int L = Next[i-k];
if(i+L<=p) Next[i] = L; else
{
j = max(, p-i+);
while(i+j<m && x[i+j]==x[+j]) j++;
Next[i] = j;
k = i;
}
}
} //next[i]: x[i...m-1] 与 x[0...m-1]的最长公共前缀
//exd[i]: y[i...n-1] 与 x[0...m-1]的最长公共前缀
void EXKMP(char x[], int m, char y[], int n, int Next[], int exd[])
{
pre_EXKMP(x,m,Next); //获取x的next数组(x与自己的匹配)
int j = ;
while(j<n && j<m && x[j]==y[j]) j++;
exd[] = j;
int k = ; //k使得k+exd[k]-1最大,即匹配得最远的y后缀
for(int i = ; i<n; i++)
{
int p = exd[k]+k-; //p为y字符串匹配得最远的位置
int L = Next[i-k]; //因为y[k...k+exd[k]-1] == x[0...exd[k]-1]
//所以y[i...k+exd[k]-1] == x[i-k...exd[k]-1]
//我们已知: x[i-k...] 与 x[0...]的最长公共前缀为next[i-k]
//那么我们可以利用next[i-k]的到:y[i...] 与 x[0...]至少匹配了多少个字符
//然后i+next[i-k]就是以i为起始,目前为止匹配得最远的地方。
//如果i+next[i-k]<=p,即小于等于之前匹配最远的,那么exd[i]就等于i+next[i-k]
//否则,之后的字符不能确定是否匹配,所以要继续匹配下去,然后设置k为i
if(i+L<=p) exd[i] = L;
else
{
j = max(,p-i+); //p-i+1即通过next[i-k]得知的y[i...]与x[0...]至少匹配的字符个数
while(i+j<n && j<m && y[i+j]==x[+j]) j++;
exd[i] = j;
k = i;
}
}
} char s1[MAXN], s2[MAXN];
int val[], Next[MAXN], exd1[MAXN], exd2[MAXN], sum[MAXN]; int main()
{
int T;
scanf("%d",&T);
while(T--)
{
for(int i = ; i<; i++)
scanf("%d",&val[i]);
scanf("%s",s1); int len = strlen(s1);
sum[] = val[s1[]-'a'];
for(int i = ; i<len; i++)
sum[i] = sum[i-] + val[s1[i]-'a']; memcpy(s2, s1, sizeof(s2)); //复制并反转
reverse(s2, s2+len); EXKMP(s1, len, s2, len, Next, exd1); //前缀
EXKMP(s2, len, s1, len, Next, exd2); //后缀
int ans = ;
reverse(exd1, exd1+len); //这样exd1就是前缀, exd2就是后缀了。
for(int i = ; i<len-; i++)
{
int tmp = ;
if(exd1[i]==i+) tmp += sum[i];
if(exd2[i+]==len-(i+)) tmp += sum[len-]-sum[i];
ans = max(ans,tmp);
}
printf("%d\n", ans);
}
}

HDU3613 Best Reward —— Manacher算法 / 扩展KMP + 枚举的更多相关文章

  1. manacher 和 扩展KMP

    manacher 和 扩展KMP 事实上,这两个东西是一样的. 考虑 manacher 的过程 我们实时维护最远扩展的位置 \(mx\) 以及这个回文串的回文中心 \(l\) ,那么显然当然位置如果没 ...

  2. hdu 3613"Best Reward"(Manacher算法)

    传送门 题意: 国王为了犒劳立下战功的大将军Li,决定奖给Li一串项链,这个项链一共包含26中珠子"a~z",每种珠子都有 相应的价值(-100~100),当某个项链可以构成回文时 ...

  3. hdu3613 Best Reward manacher+贪心+前缀和

    After an uphill battle, General Li won a great victory. Now the head of state decide to reward him w ...

  4. hdu3613 Best Reward 扩展kmp or O(n)求最大回文子串

    /** 题目:hdu3613 Best Reward 链接:http://acm.hdu.edu.cn/showproblem.php?pid=3613 题意:有一个字符串,把他切成两部分. 如果这部 ...

  5. KMP 、扩展KMP、Manacher算法 总结

    一. KMP 1 找字符串x是否存在于y串中,或者存在了几次 HDU1711 Number Sequence HDU1686 Oulipo HDU2087 剪花布条 2.求多个字符串的最长公共子串 P ...

  6. 浅谈Manacher算法与扩展KMP之间的联系

    首先,在谈到Manacher算法之前,我们先来看一个小问题:给定一个字符串S,求该字符串的最长回文子串的长度.对于该问题的求解.网上解法颇多.时间复杂度也不尽同样,这里列述几种常见的解法. 解法一   ...

  7. [扩展KMP][HDU3613][Best Reward]

    题意: 将一段字符串 分割成两个串 如果分割后的串为回文串,则该串的价值为所有字符的权值之和(字符的权值可能为负数),否则为0. 问如何分割,使得两个串权值之和最大 思路: 首先了解扩展kmp 扩展K ...

  8. ACM之路(12)—— KMP & 扩展KMP & Manacher

    最近做完了kuangbin的一套关于kmp的题目(除了一道字典树的不会,因为还没学字典树所以先放放),做个总结.(kuangbin题目的链接:http://acm.hust.edu.cn/vjudge ...

  9. KMP && Manacher && 扩展KMP整理

    KMP算法: kmp示例代码: void cal_next(char *str, int *next, int len) { next[0] = -1;//next[0]初始化为-1,-1表示不存在相 ...

随机推荐

  1. 洛谷试炼场 提高模板-nlogn数据结构

    树状数组-区间求和 P3374 [模板]树状数组 1 /*by SilverN*/ #include<algorithm> #include<iostream> #includ ...

  2. BB FlashBack pro导出AVI格式的配置参数

    文件-->导出,选择AVI格式在选择AVI解码器中选择Cinepak Codec by Radius压缩质量:建议6~12%点击确定在AVI导出选项中选择帧速率:4帧每秒音频选择格式 11.02 ...

  3. Executors

    提供了工厂方法: Factory and utility methods for Executor, ExecutorService, ScheduledExecutorService, Thread ...

  4. CAN 和 CANopen的区别和联系

    1.CAN与CANopen的共同点与不同点:  CAN只定义了物理层与链路层,而没有定义用户层,用户可根据自己的需要定义一些网络上的通信约定:  CANopen是在CAN的基础上定义了用户层,即规定了 ...

  5. 转 vs2010转vs2008 其他的一样

    如果你使用VS2010的任何版本写代码,那么在VS2008中就不能打开VS2010的解决方案了,为此,通过以下三步就可以解决了一.对于工程名.sln; 1.用你喜欢的编辑器打开sln文件,比如note ...

  6. Android-屏幕适配经验总结

    本文记录一些适配问题的研究,基础概念不做过多介绍. Android在做屏幕适配的时候一般考虑两个因素:分辨率和dpi.分辨率是屏幕在横向.纵向上的像素点数总和,一般用"宽x高"的形 ...

  7. uiimage缩放图片大小和属性UIViewContentModeScaleAspectFit

    UIImageView *tmp = [[UIImageView alloc]initWithFrame:CGRectMake(5.0f, 5.0f, 40.0f, 40.0f)];          ...

  8. linux命令stat,查看文件详细信息

    可以查看文件的各类具体信息:文件权限的数字形式0664:uid.gid的权限的数字形式等 更多用法参考stat --help lsattr test.sh 查看文件的其他属性:只读属性.只可以追加写属 ...

  9. 如何用Python批量发现互联网“开放”摄像头

    现在无论家用还是公司使用摄像头越来越多,但是安全性又如何呐?今天我来说说几款比较常用的摄像头,并且使用python如何批量检查弱口令. 第一个“海康威视”: 前段时间爆出海康威视的摄像头存在默认弱口令 ...

  10. Codeforces 424 C. Magic Formulas

    xor是满足交换律的,展开后发现仅仅要能高速求出 [1mod1....1modn],....,[nmod1...nmodn]的矩阵的xor即可了....然后找个规律 C. Magic Formulas ...