hdu 3613"Best Reward"(Manacher算法)
题意:
国王为了犒劳立下战功的大将军Li,决定奖给Li一串项链,这个项链一共包含26中珠子"a~z",每种珠子都有
相应的价值(-100~100),当某个项链可以构成回文时,那么这个项链的价值就是每个珠子价值的加和,如果
构不成,那么这个项链的价值就为0;
求如何将国王奖赏的一串项链拆成价值加和最大的两串项链,求出这个最大价值。
题解:
本来我是在找有关拓展KMP的相关题目的,百度到一大牛的博客(“扩展KMP题目”),当做到第二个题目的时候,
思来想去,就是没找到其和拓展KMP的联系,然后,感觉可以用Manacher算法,刷刷刷撸了个Manacher的代码
提交,AC,所以,我暂且谈谈如何用Manacher算法解这道题;
①首先将项链串s[]预处理(了解Manacher算法就理解啥意思了);
②准备一个数组sum[],sum[ i ]:预处理后的数组中前 i 个字符对应的价值的加和,'#'当作0;
③使用Manacher算法求解出回文半径数组radius[];
④假设从 i 位置切割项链,将项链分成[ 0,i ],[ i,len-1 ]两串,分别求解对应的总价值,令ans=max{从i位置分割的总价值}
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define INF 0x3f3f3f3f
#define lowbit(x) (x&-x)
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn=5e5+; int val[];
char s[*maxn];
char temp[maxn];
int radius[*maxn];
int sum[*maxn];
void Trans()
{
int len=strlen(s);
strcpy(temp,s);
for(int i=;i < len;++i)
{
s[*i]='#';
s[*i+]=temp[i];
}
s[*len]='#';
s[*len+]='\0';
}
void Manacher()
{
mem(radius,);
int len=strlen(s);
int R=;
int K=;
radius[]=;
for(int i=;i < len;++i)
{
int cnt=;
if(i >= R)
{
while(i+cnt < len && i-cnt >= && s[i+cnt] == s[i-cnt])
cnt++;
radius[i]=cnt;
if(i+cnt- > R)
{
R=i+cnt-;
K=i;
}
}
else
{
int j=K-(i-K);
if(i+radius[j]- != R)
radius[i]=min(R-i+,radius[j]);
else
{
cnt=R-i+;
while(i-cnt >= && i+cnt < len && s[i-cnt] == s[i+cnt])
cnt++;
radius[i]=cnt;
if(i+cnt- > R)
{
R=i+cnt-;
K=i;
}
}
}
}
}
int Solve()
{
Trans();//预处理字符串s
Manacher(); int len=strlen(s);
sum[]=;
for(int i=;i < len;++i)//前缀和
sum[i]=sum[i-]+(s[i] == '#' ? :val[s[i]-'a']); int ans=-INF;
for(int i=;i < len-;i+=)
{
int cnt=;
int x=(i+)>>;//[0,i+1]的中点坐标
if(radius[x] == x+)//判断[0,i]是否构成回文子串
cnt += sum[i]; int y=(len+i)>>;//[i+1,len-1]的中点坐标
if(radius[y] == len-y)//判断[i+1,len-1]是否构成回文子串
cnt += sum[len-]-sum[i];
ans=max(ans,cnt);
}
return ans;
}
int main()
{
// freopen("C:/Users/hyacinthLJP/Desktop/stdin/contest","r",stdin);
int test;
scanf("%d",&test);
while(test--)
{
for(int i=;i < ;++i)
scanf("%d",val+i);
scanf("%s",s);
printf("%d\n",Solve());
}
return ;
}
hdu 3613"Best Reward"(Manacher算法)的更多相关文章
- HDU 3613 Best Reward(KMP算法求解一个串的前、后缀回文串标记数组)
题目链接: https://cn.vjudge.net/problem/HDU-3613 After an uphill battle, General Li won a great victory. ...
- HDU 3613 Best Reward 正反两次扩展KMP
题目来源:HDU 3613 Best Reward 题意:每一个字母相应一个权值 将给你的字符串分成两部分 假设一部分是回文 这部分的值就是每一个字母的权值之和 求一种分法使得2部分的和最大 思路:考 ...
- HDU 3613 Best Reward(manacher求前、后缀回文串)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3613 题目大意: 题目大意就是将字符串s分成两部分子串,若子串是回文串则需计算价值,否则价值为0,求分 ...
- HDU - 3613 Best Reward(manacher或拓展kmp)
传送门:HDU - 3613 题意:给出26个字母的价值,然后给你一个字符串,把它分成两个字符串,字符串是回文串才算价值,求价值最大是多少. 题解:这个题可以用马拉车,也可以用拓展kmp. ①Mana ...
- hdu 3613 Best Reward
After an uphill battle, General Li won a great victory. Now the head of state decide to reward him w ...
- HDU3613 Best Reward —— Manacher算法 / 扩展KMP + 枚举
题目链接:https://vjudge.net/problem/HDU-3613 Best Reward Time Limit: 2000/1000 MS (Java/Others) Memor ...
- HDU 3613 Best Reward(拓展KMP算法求解)
题目链接: https://cn.vjudge.net/problem/HDU-3613 After an uphill battle, General Li won a great victory. ...
- hdu 3613 Best Reward (manachar算法)
Best Reward Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Prob ...
- HDU 3613 Best Reward ( 拓展KMP求回文串 || Manacher )
题意 : 给个字符串S,要把S分成两段T1,T2,每个字母都有一个对应的价值,如果T1,T2是回文串,那么他们就会有一个价值,这个价值是这个串的所有字母价值之和,如果不是回文串,那么这串价值就为0.问 ...
随机推荐
- 阿里云ECS服务器,CentOS 7.4配置jdk+tomcat+mysql
参考博客: https://mp.weixin.qq.com/s?__biz=MzIxMzk3Mjg5MQ==&mid=2247484020&idx=1&sn=6e0aa07f ...
- 一、纯css实现顶部进度条随滚动条滚动
一.效果图 二.直接复制粘贴 <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...
- Running ASP.NET Core applications on Windows Subsystem for Linux
Setting up Linux on Windows 10 First thing is to enable Windows Subsystem for Linux. It doesn’t inst ...
- centOS7 下配置和启动maria数据库
从最新版本的linux系统开始,默认的是 Mariadb而不是mysql! 使用系统自带的repos安装很简单: yum install mariadb mariadb-server systemct ...
- CSS3 flexbox 布局 ---- flex项目属性介绍
现在介绍用在flex项目上的css 属性,html结构还是用ul, li 结构,不过内容改成1,2,3, 样式的话,直接把给 ul 设display:flex 变成flex 容器,默认主轴的方向为水平 ...
- Codeforces Round #446 Div. 1
B:即使看到n<=22也应该猜到这只是为了写spj.将每个数替换为恰好比他大的数即可,最大值替换为最小值.这样原序列中不包含最小值的集合显然都满足条件,并且容易发现包含最小值的集合的变化量都是最 ...
- Spring03-AOP
一. AOP介绍 1. Aop介绍 AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编 ...
- Tarjan总结(缩点+割点(边)+双联通+LCA+相关模板)
Tarjan求强连通分量 先来一波定义 强连通:有向图中A点可以到达B点,B点可以到达A点,则称为强连通 强连通分量:有向图的一个子图中,任意两个点可以相互到达,则称当前子图为图的强连通分量 强连通图 ...
- MT【254】值域包含值域
已知函数$f(x)=x-\dfrac{1}{1+x},g(x)=x^2-2ax+4,$若对任意$x_1\in[0,1]$,存在$x_2\in[1,2]$,使得$f(x_1)=g(x_2)$,则实数$a ...
- python学习日记(基础数据类型及其方法02)
python的变量 python中的变量不需要声明,变量载使用前必须被赋值,变量被赋值以后才会被创建. 在python中变量就是变量,没有数据类型.我们所说的类型是变量所指向内存中的对象的类型. py ...