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表示不存在相 ...
随机推荐
- 用 Jackson 来处理 JSON
Jackson 是一个 Java 用来处理 JSON 格式数据的类库,性能非常好. 首先创建一个User对象类 (User.java) package com.sivalabs.json; impor ...
- 文艺平衡树(bzoj 3223)
Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 ...
- 三类(创结行),23种设计模式,速记理解法!PHP
一,创建型设计模式 1.FACTORY—追MM少不了请吃饭了,麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西,虽然口味有所不同,但不管你带MM去麦当劳或肯德基,只管向服务员说“来四个鸡翅”就行了.麦当劳 ...
- golang-random随机数
在Golang中,有两个包提供了rand,分别为 "math/rand" 和 "crypto/rand", 对应两种应用场景. 一."math/ra ...
- TCP No-Delay
Nagle 算法 由于TCP中包头的大小是固定的,所以在数据(Payload)大小很小的时候IP报文的有效传输率是很低的,Nagle算法就是将多个即将发送的小段的用户数据,缓存并合并成一个大段数据时, ...
- LOJ#3083.「GXOI / GZOI2019」与或和_单调栈_拆位
#3083. 「GXOI / GZOI2019」与或和 题目大意 给定一个\(N\times N\)的矩阵,求所有子矩阵的\(AND(\&)\)之和.\(OR(|)\)之和. 数据范围 \(1 ...
- python3.x之print()
1.print内容 #!/usr/bin/python print('hello world') //print("hello world") 2.print变量 #!/us ...
- IOS --关于粘贴板 ,剪切板 ,UILabel的复制
在iOS中下面三个控件,自身就有复制-粘贴的功能: 1.UITextView 2.UITextField 3.UIWebView UIKit framework提供了几个类和协议方便我们在自己的应用程 ...
- linxu下查看进程的线程方法;如何知道某个进程或者线程运行在哪个CPU上?
1.top -H -p <pid> ; top -H 在top命令后,按H键:或者top -H 2.ps -T -p <pid> “-T”选项可以开启线程查看 3.htop, ...
- HDU 4422 The Little Girl who Picks Mushrooms(数学)
题目链接:http://acm.hdu.edu.cn/showproblem.php? pid=4422 Problem Description It's yet another festival s ...