hdu3613 Best Reward 扩展kmp or O(n)求最大回文子串
/**
题目:hdu3613 Best Reward
链接:http://acm.hdu.edu.cn/showproblem.php?pid=3613
题意:有一个字符串,把他切成两部分。
如果这部分是回文串,那么他的值为所有字母的权值和。否则这部分值为0;这两部分的值和为该切法的权值。
求最大的切法的权值。
思路:
如果能够判断[0,i],[i,n-1]是一个回文串(0<=i<n)那么就可以枚举i,计算切割位置为i时候两部分的贡献和。
取最大的。
利用O(n)的算法求最长回文子串的做法获得f[i];表示以第i个字符为中心的最长回文子串的长度;
就可以获得l[i],r[i];
l[i]=1表示[0,i]是一个回文串.r[i]=1表示[i,n-1]是一个回文串。 */
#include <cstdio>
#include <cstring>
#include <algorithm>
#include<set>
#include <iostream>
#include <vector>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 1e6+;///给定的长度
char s[maxn*], t[maxn];///要乘以2,因为构造了'*'
int f[maxn*];///令f[i] 表示以第i个字符为中心的最长回文子串的长度
int sum[maxn*], w[];
int l[maxn*], r[maxn*];///l[i]=1表示[0,i]是一个回文串.r[i]=1表示[i,n-1]是一个回文串。
int longest(char *a)///最长回文子串
{
int z = ;
for(int i = ; a[i]!='\0'; i++){
s[z++] = a[i];
s[z++] = '*';
}
z--;
s[z] = '\0';
int j = ;
int ans = ;
f[] = ;
for(int i = ; i < z; i++){
if(f[j]-*(i-j)<=) {
f[i] = ;
}else{
f[i] = min(f[*j-i],f[j]-*(i-j));
}
int l = i-f[i]/-, r = i+f[i]/+;
while(l>=&&r<z&&s[l]==s[r]){
l--, r++;
f[i]+=;
}
if(f[i]/+i>f[j]/+j){
j = i;
}
if(f[i]>ans){
ans = f[i];
}
}
int mas = ;
for(int i = ; i < z; i++){
if(f[i]==ans){
int l = i-f[i]/, r = i+f[i]/;
int cnt;
if(s[l]=='*'){
cnt = f[i]/;
}else cnt = f[i]/+;
mas = max(mas,cnt);
}
}
return mas;
}
int main()
{
//freopen("in.txt","r",stdin);
int T;
int cas = ;
cin>>T;
while(T--){
for(int i = ; i < ; i++) scanf("%d",&w[i]);
scanf("%s",t);
longest(t);
int n = strlen(s);
sum[] = w[s[]-'a'];
for(int i = ; i < n; i++){
if(s[i]=='*') sum[i] = sum[i-]+;
else sum[i] = sum[i-]+w[s[i]-'a'];
}
memset(l, , sizeof l);
memset(r, , sizeof r);
for(int i = ; i < n; i++){
int L = i-(f[i]-)/;
int R = i+(f[i]-)/;
if(L==){
l[R] = ;
}
if(R==n-){
r[L] = ;
}
}
int ans = -INF, ansa, ansb;
for(int i = ; i < n-; i++){
if(i%){
if(l[i-]){
ansa = sum[i-];
}else ansa = ;
if(r[i+]){
ansb = sum[n-]-sum[i-];
}else ansb = ;
}else
{
if(l[i-]){
ansa = sum[i-];
}else ansa = ;
if(r[i]){
ansb = sum[n-]-sum[i-];
}else ansb = ;
} ans = max(ans,ansa+ansb);
}
printf("%d\n",ans);
}
return ;
}
/**
题目:hdu3613 Best Reward
链接:http://acm.hdu.edu.cn/showproblem.php?pid=3613
题意:有一个字符串,把他切成两部分。
如果这部分是回文串,那么他的值为所有字母的权值和。否则这部分值为0;这两部分的值和为该切法的权值。
求最大的切法的权值。
思路:
如果能够判断[0,i],[i,n-1]是一个回文串(0<=i<n)那么就可以枚举i,计算切割位置为i时候两部分的贡献和。
取最大的。 扩展kmp的做法。
先计算l[i]=1,表示[0,i]是一个回文串;那么[0,k1]与[k2,i]相等。0是固定的。
获得原串t的反转串s。求extend[i],表示s串从[i,n-1]与原串t的最长公共前缀。
枚举s串的i。那么从[i,n-1]的长度n-i;如果extend[i]*2+1>=n-i那么表示原串t中的[0,n-1-i]是一个回文串即l[n-1-i] = 1; 现在求r[i]=1,表示[i,n-1]是一个回文串;那么[i,k1]与[k2,n-1]相等。n-1是固定的。
求extend[i],表示t串从[i,n-1]与s串的最长公共前缀。
枚举t串的i。那么从[i,n-1]的长度为n-i;如果extend[i]*2+1>=n-i那么表示原串[i,n-1]是一个回文串即r[i] = 1; */
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
#include <iostream>
#include <vector>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 5e5+;
char s[maxn], t[maxn];
int f[maxn], Next[maxn], extend[maxn];
int sum[maxn], w[];
int l[maxn], r[maxn];///l[i]=1表示[0,i]是一个回文串.r[i]=1表示[i,n-1]是一个回文串。
void GetNext(char *T,int* next)
{
int a=;
int Tlen=strlen(T);
next[]=Tlen;
while(a<Tlen-&&T[a]==T[a+]) a++;
next[]=a;
a=;
for(int k=;k<Tlen;k++)
{
int p=a+next[a]-,L=next[k-a];
if((k-)+L>=p)
{
int j=(p-k+)>? p-k+:;
while(k+j<Tlen&&T[k+j]==T[j]) j++;
next[k]=j;
a=k;
}
else next[k]=L;
}
} void GetExtend(char *S,char *T,int* next,int* extend)
{
int a=;
GetNext(T,next);
int Slen=strlen(S);
int Tlen=strlen(T);
int MinLen=Slen<Tlen? Slen:Tlen;
while(a<MinLen&&S[a]==T[a]) a++;
extend[]=a;
a=;
for(int k=;k<Slen;k++)
{
int p=a+extend[a]-,L=next[k-a];
if((k-)+L>=p)
{
int j=(p-k+)>? p-k+:;
while(k+j<Slen&&j<Tlen&&S[k+j]==T[j]) j++;
extend[k]=j;
a=k;
}
else extend[k]=L;
}
}
void getlr(int* extend,int *l,int flag,int n)
{
int len;
for(int i = ; i < n; i++){
len = n-i;
if(extend[i]*+>=len){
if(flag) l[i] = ;
else l[n--i] = ;
}
}
}
void test(int *f,int n)
{
for(int i = ; i < n; i++){
printf("f[%d] = %d\n",i,f[i]);
}
}
int main()
{
//freopen("in.txt","r",stdin);
int T;
cin>>T;
while(T--){
for(int i = ; i < ; i++) scanf("%d",&w[i]);
scanf("%s",t);
int n = strlen(t);
for(int i = ; i < n; i++) s[n--i] = t[i];
s[n] = '\0';
sum[] = w[t[]-'a'];
for(int i = ; i < n; i++){
sum[i] = sum[i-]+w[t[i]-'a'];
}
memset(l, , sizeof l);
memset(r, , sizeof r); GetExtend(s,t,Next,extend);
getlr(extend,l,,n); GetExtend(t,s,Next,extend);
getlr(extend,r,,n); int ans = -INF, ansa, ansb;
for(int i = ; i < n; i++){
if(l[i-]){
ansa = sum[i-];
}else ansa = ;
if(r[i]){
ansb = sum[n-]-sum[i-];
}else ansb = ;
ans = max(ans,ansa+ansb);
}
printf("%d\n",ans);
}
return ;
}
hdu3613 Best Reward 扩展kmp or O(n)求最大回文子串的更多相关文章
- [LeetCode] 647. 回文子串 ☆☆☆(最长子串、动态规划、中心扩展算法)
描述 给定一个字符串,你的任务是计算这个字符串中有多少个回文子串. 具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被计为是不同的子串. 示例 1: 输入: "abc" ...
- 【LeetCode】最长回文子串【动态规划或中心扩展】
给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示例 1: 输入: "babad"输出: "bab"注意: " ...
- S - Best Reward 扩展KMP
After an uphill battle, General Li won a great victory. Now the head of state decide to reward him w ...
- HDU 3613 Best Reward(扩展KMP求前后缀回文串)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3613 题目大意: 大意就是将字符串s分成两部分子串,若子串是回文串则需计算价值,否则价值为0,求分割 ...
- Best Reward HDU 3613(回文子串Manacher)
题目大意:有一个串(全部由小写字母组成),现在要把它分成两部分,如果分开后的部分是回文串就计算出来它的价值总和,如果不是回文的那么价值就是0,最多能得到的最大价值. 分析:首先的明白这个最大价值有 ...
- KMP && Manacher && 扩展KMP整理
KMP算法: kmp示例代码: void cal_next(char *str, int *next, int len) { next[0] = -1;//next[0]初始化为-1,-1表示不存在相 ...
- [扩展KMP][HDU3613][Best Reward]
题意: 将一段字符串 分割成两个串 如果分割后的串为回文串,则该串的价值为所有字符的权值之和(字符的权值可能为负数),否则为0. 问如何分割,使得两个串权值之和最大 思路: 首先了解扩展kmp 扩展K ...
- KMP 、扩展KMP、Manacher算法 总结
一. KMP 1 找字符串x是否存在于y串中,或者存在了几次 HDU1711 Number Sequence HDU1686 Oulipo HDU2087 剪花布条 2.求多个字符串的最长公共子串 P ...
- HDU 3613 Best Reward(KMP算法求解一个串的前、后缀回文串标记数组)
题目链接: https://cn.vjudge.net/problem/HDU-3613 After an uphill battle, General Li won a great victory. ...
随机推荐
- [Python爬虫] 之十:Selenium +phantomjs抓取活动行中会议活动
一.介绍 本例子用Selenium +phantomjs爬取活动树(http://www.huodongshu.com/html/find_search.html?search_keyword=数字) ...
- Java笔记19:Java匿名内部类
匿名内部类也就是没有名字的内部类.正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写.但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口 例1:不使用匿名内部类来实现抽象方 ...
- 【云计算】k8s相关资料
参考资料: How to get started, and achieve tasks, using Kubernetes:http://kubernetes.io/docs/getting-star ...
- JSP中的TAG文件和TLD文件小结
在jsp文件中,可以引用tag和tld文件. 1.对于tag文件 <%@ taglib prefix="ui" tagdir="/WEB-INF/tags" ...
- 给Swing的GUI组件设置前景色和背景色
JButton btn=new JButton("TEST"); btn.setForeground(Color.white);// 设置前景色(文字颜色)btn.setBackg ...
- Android 歌词显示
一.概述 项目中设计到歌词显示的问题,这一块之前没有涉及过,只是套用过一个开源的项目,效果还行,于是想到拿来稍作修改,以适应项目需求. 二.歌词控件 先来看下这个自定义控件写的歌词控件吧: publi ...
- webDriver API——第7部分Desired Capabilities
The Desired Capabilities implementation. class selenium.webdriver.common.desired_capabilities.Desire ...
- VUE购物车示例
代码下载地址:https://github.com/MengFangui/VueShoppingCart 1.index.html <!DOCTYPE html> <html lan ...
- 安卓Camera APP
一.Camera package android.hardware 该类用于设定图像捕获设置,开启/关闭预览,抓拍图片以及获取帧用于编码视频.这个类是Camera服务的客户端,用 ...
- Drupal启动阶段之一:配置
配置是Drupal启动过程中的第一个阶段,通过函数_drupal_bootstrap_configuration()实现: function _drupal_bootstrap_configurati ...