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. ...
随机推荐
- Java笔记18:JUnit单元测试
1 从http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22junit%22%20AND%20a%3A%22junit%22 上下载最新的junit包. ...
- docker学习笔记-1
docker学习笔记一:安装 mac安装docker docker官方文档上有这么一段话: Because the Docker daemon uses Linux-specific kernel f ...
- MP3中设置播放顺序的软件《闪存式MP3伴侣》
给姥爷买了一个插卡音箱,里面拷贝了几百段评书,每一段评书都是一个mp3文件,虽然插卡音箱会自动一个文件一个文件自动播放,可是比较郁闷的是评书的播放顺序完全是乱的,毫无规律可寻,本来我的mp3文件的文件 ...
- WebService 之 工作原理
一.Web Service基本概念 Web Service 也叫 XML Web Service,WebService 是一种可以接收从Internet或者Intranet上的其它系统中传递过来的请求 ...
- [学习笔记—Objective-C]《Objective-C-基础教程 第2版》第九章 内存管理
内存管理: 确保在须要的时候分配内存,在程序运行结束时释放占用的内存 假设仅仅分配内存而不释放内存,则会发生内存泄漏(leak memory),程序的内存占用量不断添加.终于会被耗尽并导致程序崩溃. ...
- ant-design 设置 DatePicker 默认值
1.代码 render() { const { value } = this.props; return ( <React.Fragment> { value ? <DatePick ...
- C++11 std::async 包装实体店::packaged_task
更好的方式 C++11中提供了操作多线程的高层次特性. std::packaged_task 包装的是一个异步操作,相当与外包任务,好比我大阿里把电话客服外包给某某公司. std::future 提供 ...
- Debian9.3安装NW360无线网卡驱动
最近想把家里的一台老旧台式机利用起来,打算安装Debian9.3,下载ISO,用PowerISO写入到U盘,然后开始安装,过程基本顺利. 就是中间提示缺少“rtl_nic/rtl8105e-1.fw” ...
- 【转】打造自己的视频会议系统 GGMeeting(附送源码)
原文地址:http://www.cnblogs.com/justnow/p/4487201.html 自从在博客园发布开源即时通信系统GG(QQ高仿版)以来,结识了很多做IM的朋友,然后我和我的伙伴们 ...
- vs2017搭建自己的nuget服务器
准备环境 vs2017 第一步 创建一个新的asp.net 空网站 .net框架使用4.6以上版本 (或者在第二部中使用低版本的nuget server) 第二步 打开nuget包管理器 搜索nu ...