HDU3613 Best Reward —— Manacher算法 / 扩展KMP + 枚举
题目链接: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
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.
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.
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
6
题解:
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 + 枚举的更多相关文章
- manacher 和 扩展KMP
manacher 和 扩展KMP 事实上,这两个东西是一样的. 考虑 manacher 的过程 我们实时维护最远扩展的位置 \(mx\) 以及这个回文串的回文中心 \(l\) ,那么显然当然位置如果没 ...
- hdu 3613"Best Reward"(Manacher算法)
传送门 题意: 国王为了犒劳立下战功的大将军Li,决定奖给Li一串项链,这个项链一共包含26中珠子"a~z",每种珠子都有 相应的价值(-100~100),当某个项链可以构成回文时 ...
- hdu3613 Best Reward manacher+贪心+前缀和
After an uphill battle, General Li won a great victory. Now the head of state decide to reward him w ...
- hdu3613 Best Reward 扩展kmp or O(n)求最大回文子串
/** 题目:hdu3613 Best Reward 链接:http://acm.hdu.edu.cn/showproblem.php?pid=3613 题意:有一个字符串,把他切成两部分. 如果这部 ...
- KMP 、扩展KMP、Manacher算法 总结
一. KMP 1 找字符串x是否存在于y串中,或者存在了几次 HDU1711 Number Sequence HDU1686 Oulipo HDU2087 剪花布条 2.求多个字符串的最长公共子串 P ...
- 浅谈Manacher算法与扩展KMP之间的联系
首先,在谈到Manacher算法之前,我们先来看一个小问题:给定一个字符串S,求该字符串的最长回文子串的长度.对于该问题的求解.网上解法颇多.时间复杂度也不尽同样,这里列述几种常见的解法. 解法一 ...
- [扩展KMP][HDU3613][Best Reward]
题意: 将一段字符串 分割成两个串 如果分割后的串为回文串,则该串的价值为所有字符的权值之和(字符的权值可能为负数),否则为0. 问如何分割,使得两个串权值之和最大 思路: 首先了解扩展kmp 扩展K ...
- ACM之路(12)—— KMP & 扩展KMP & Manacher
最近做完了kuangbin的一套关于kmp的题目(除了一道字典树的不会,因为还没学字典树所以先放放),做个总结.(kuangbin题目的链接:http://acm.hust.edu.cn/vjudge ...
- KMP && Manacher && 扩展KMP整理
KMP算法: kmp示例代码: void cal_next(char *str, int *next, int len) { next[0] = -1;//next[0]初始化为-1,-1表示不存在相 ...
随机推荐
- oracle禁止插入、延迟插入方法
DATE_ADD(DATE_ADD(curdate(),INTERVAL +6 HOUR),INTERVAL +6 DAY) mysql取当前日期后6天,截止到6点钟的方法 --直接报错 CREATE ...
- mock数据。根据表中一天的数据模拟其他日期的数据
package test; import java.sql.*; import java.text.SimpleDateFormat; import java.util.*; import java. ...
- 染色(bzoj 2243)
Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“ ...
- formSubmit
精简代码: <form name='form0001' method="post"> .... <li id="view"><a ...
- CentOS6、CentOS7配置Base源和epel源
1.用yum安装软件报错 Could not retrieve mirrorlist http://mirrorlist.centos.org/?release=6&arch=x86_64&a ...
- springboot启动报异常,Failed to load property source from location 'classpath:/application.yml'
学习springboot,在启动时抛出下图异常 往下看异常信息,找到异常的具体位置 找到application.yml文件的对应位置,发现params配置前面多了空格 去掉空格重新启动,可以了 写代码 ...
- Maven的相关问题(一)——settings.xml配置详解
工作中第一次正式接触maven,虽然之前在学习时有遇到过,但是对于maven的认识和理解确实太浅薄,仅仅局限于机械式的操,纸上得来终觉浅,绝知此事要躬行···古人诚不欺我也~ 下面先贴一个找到的一个非 ...
- Windows Server 远程桌面报错:No Remote Desktop License Servers Available
问题描述: 在用远程桌面访问Window Server服务器时,出现如下错误: The remote session was disconnected because there are no Rem ...
- android开发教程之使用线程实现视图平滑滚动示例
最近一直想做下拉刷新的效果,琢磨了好久,才走到通过onTouch方法把整个视图往下拉的步骤,接下来就是能拉下来,松开手要能滑回去啊.网上看了好久,没有找到详细的下拉刷新的例子,只有自己慢慢琢磨了.昨天 ...
- [NPM] Set default values for package.json using npm set
Npm by default uses global values when initializing a new package.json file. Learn how to set your o ...