HDU - 3613 Best Reward(manacher或拓展kmp)
传送门:HDU - 3613
题意:给出26个字母的价值,然后给你一个字符串,把它分成两个字符串,字符串是回文串才算价值,求价值最大是多少。
题解:这个题可以用马拉车,也可以用拓展kmp。
①Manacher:先记录下第i个字符的价值,然后求前缀和。然后遍历分的位置,分别判断前半段和后半段是否为回文串,是回文串的加上这段的价值(前缀和相减),更新最大价值。
1 #include<bits/stdc++.h>
2 using namespace std;
3
4 int p[1000100],val[500100];
5 char s[500100];
6 map<char,int> mp;
7
8 void Manacher(char str[])
9 {
10 memset(p,0,sizeof(p));
11 string s="$#";
12 int len=strlen(str);
13 for(int i=0;i<len;i++){
14 s+=str[i];
15 s+='#';
16 }
17 int mx=0,id=0,reslen=0,rescenter=0;
18 len=s.length();
19 for(int i=1;i<=len;i++){
20 if(mx>i) p[i]=min(p[2*id-i],mx-i);
21 else p[i]=1;
22 while(s[i+p[i]]==s[i-p[i]]) p[i]++;
23 if(mx<i+p[i]){
24 mx=i+p[i];
25 id=i;
26 }
27 }
28 }
29
30 int main()
31 {
32 int t;
33 cin>>t;
34 while(t--){
35 mp.clear();
36 for(int i=0;i<26;i++){
37 int x;
38 cin>>x;
39 mp['a'+i]=x;
40 }
41 cin>>s;
42 int len=strlen(s);
43 for(int i=0;i<len;i++){
44 if(!i) val[i]=mp[s[i]];
45 else val[i]=val[i-1]+mp[s[i]];
46 }
47 int ans=0;
48 Manacher(s);
49 for(int i=1;i<len;i++){
50 int p1=0,p2=0;
51 int x=i*2+1;
52 x=x/2+1; ///<i的串的中心位置
53 int y=(len-i)*2+1;
54 y=y/2+1;
55 y=(len*2+2)-y; ///剩下部分的中心位置
56 if(p[x]==x) p1=val[i-1];
57 if(p[y]+y==len*2+2) p2=val[len-1]-val[i-1];
58 ans=max(ans,p1+p2);
59 }
60 cout<<ans<<endl;
61 }
62 return 0;
63 }
②拓展kmp:用原串和反串进行比较,第一次原串做主串,第二次反串做主串。遍历分的位置,如果ex1[i]+i==len,那么说明s中的0~i-1为回文串,如果ex2[len-i]==i,说明s中的i~len-1为回文串,是回文串的价值加上,记录最大的价值。
1 #include<bits/stdc++.h>
2 using namespace std;
3
4 ///next[i]: T[i]到T[m - 1]与T(模式串)的最长相同前缀长度;
5 ///extend[i]: S[i]到S[n - 1](原串)与T的最长相同前缀长度。
6
7 const int maxn=500100; //字符串长度最大值
8 int nt[maxn],ex1[maxn],ex2[maxn]; //ex数组即为extend数组
9 int val[30];
10
11 //预处理计算next数组
12 void GETNEXT(char *str)
13 {
14 int i=0,j,po,len=strlen(str);
15 nt[0]=len; //初始化nt[0]
16 while(str[i]==str[i+1]&&i+1<len) i++; //计算nt[1]
17 nt[1]=i;
18 po=1; //初始化po的位置
19 for(i=2;i<len;i++){
20 if(nt[i-po]+i<nt[po]+po) nt[i]=nt[i-po]; //第一种情况,可以直接得到nt[i]的值
21 else{ //第二种情况,要继续匹配才能得到nt[i]的值
22 j=nt[po]+po-i;
23 if(j<0) j=0; //如果i>po+nt[po],则要从头开始匹配
24 while(i+j<len&&str[j]==str[j+i]) j++; //计算nt[i]
25 nt[i]=j;
26 po=i; //更新po的位置
27 }
28 }
29 }
30
31 //计算extend数组
32 void EXKMP(char *s1,char *s2,int *ex) ///s1的后缀和s2的前缀匹配
33 {
34 int i=0,j,po,len=strlen(s1),l2=strlen(s2);
35 GETNEXT(s2); //计算子串的next数组
36 while(s1[i]==s2[i]&&i<l2&&i<len) i++; //计算ex[0]
37 ex[0]=i;
38 po=0; //初始化po的位置
39 for(i=1;i<len;i++){
40 if(nt[i-po]+i<ex[po]+po) ex[i]=nt[i-po]; //第一种情况,直接可以得到ex[i]的值
41 else{ //第二种情况,要继续匹配才能得到ex[i]的值
42 j=ex[po]+po-i;
43 if(j<0) j=0; //如果i>ex[po]+po则要从头开始匹配
44 while(i+j<len&&j<l2&&s1[j+i]==s2[j]) j++; //计算ex[i]
45 ex[i]=j;
46 po=i; //更新po的位置
47 }
48 }
49 }
50
51 char s[maxn];
52 int sum[maxn];
53 char p[maxn];
54
55 int main()
56 {
57 int t;
58 cin>>t;
59 while(t--){
60 for(int i=0;i<26;i++)
61 cin>>val[i];
62 cin>>s;
63 int len=strlen(s);
64 for(int i=0;i<len;i++)
65 if(!i) sum[i]=val[s[i]-'a'];
66 else sum[i]=val[s[i]-'a']+sum[i-1];
67 strcpy(p,s);
68 reverse(p,p+len);
69 EXKMP(s,p,ex1); //s做主串
70 EXKMP(p,s,ex2); //p做主串
71 int ans=0;
72 for(int i=1;i<len;i++){
73 int ans1=0,ans2=0;
74 if(ex1[i]+i==len) ans1=sum[len-1]-sum[i-1]; //s中的0~i-1;
75 if(ex2[len-i]==i) ans2=sum[i-1]; //s中的i~len-1
76 ans=max(ans,ans1+ans2);
77 }
78 cout<<ans<<endl;
79 }
80 return 0;
81 }
HDU - 3613 Best Reward(manacher或拓展kmp)的更多相关文章
- hdu 3613"Best Reward"(Manacher算法)
传送门 题意: 国王为了犒劳立下战功的大将军Li,决定奖给Li一串项链,这个项链一共包含26中珠子"a~z",每种珠子都有 相应的价值(-100~100),当某个项链可以构成回文时 ...
- HDU 3613 Best Reward 正反两次扩展KMP
题目来源:HDU 3613 Best Reward 题意:每一个字母相应一个权值 将给你的字符串分成两部分 假设一部分是回文 这部分的值就是每一个字母的权值之和 求一种分法使得2部分的和最大 思路:考 ...
- HDU 3613 Best Reward ( 拓展KMP求回文串 || Manacher )
题意 : 给个字符串S,要把S分成两段T1,T2,每个字母都有一个对应的价值,如果T1,T2是回文串,那么他们就会有一个价值,这个价值是这个串的所有字母价值之和,如果不是回文串,那么这串价值就为0.问 ...
- HDU 3613 Best Reward(拓展KMP算法求解)
题目链接: https://cn.vjudge.net/problem/HDU-3613 After an uphill battle, General Li won a great victory. ...
- HDU - 4300 Clairewd’s message (拓展kmp)
HDU - 4300 题意:这个题目好难读懂,,先给你一个字母的转换表,然后给你一个字符串密文+明文,密文一定是全的,但明文不一定是全的,求最短的密文和解密后的明文: 题解:由于密文一定是全的,所以他 ...
- 扩展KMP --- HDU 3613 Best Reward
Best Reward Problem's Link: http://acm.hdu.edu.cn/showproblem.php?pid=3613 Mean: 给你一个字符串,每个字符都有一个权 ...
- HDU 3613 Best Reward(扩展KMP求前后缀回文串)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3613 题目大意: 大意就是将字符串s分成两部分子串,若子串是回文串则需计算价值,否则价值为0,求分割 ...
- HDU 3613 Best Reward(manacher求前、后缀回文串)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3613 题目大意: 题目大意就是将字符串s分成两部分子串,若子串是回文串则需计算价值,否则价值为0,求分 ...
- HDU 3613 Best Reward(扩展KMP)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=3613 [题目大意] 一个字符串的价值定义为,当它是一个回文串的时候,价值为每个字符的价值的和,如果 ...
随机推荐
- win10中安装Linux子系统
前言 Win10的Linux子系统闻名已久,今天就来操作一下 正文 限制 该功能是win10 1809 及之后才加入的功能,故请先核对版本. 开启功能 打开windows设置 设置 -> 更新和 ...
- Ts有限状态机
ts版本的有限状态机 最近做小游戏要做切换人物状态,花点时间写了一个有限状态机,使用语言为Ts,也可改成自己的语言 按照目前的逻辑,这个可以继续横向扩展,某些做流程管理 先上预览图 Fsm:状态机类 ...
- linux源码安装软件的一般方法
rhel系统貌似安装不了xmgrace,配置的时候居然说要那个M*tif库.百度了一下,需要openmotif库,然后用root账户想要用yum安装一下这个库,搞了好久没搞懂.后面搞明白了,原因竟是因 ...
- python函数2-函数参数
rgb法则:
- MoChat - 国内首款完全开源的 PHP 企业微信管理系统正式发布
MoChat -- 让企业微信开发更简单 项目地址 Github: https://github.com/mochat-cloud/mochat Gitee: https://gitee.com/mo ...
- ctfhub技能树—信息泄露—git泄露—Stash
打开靶机环境 查看页面内容 使用dirsearch进行扫描 使用Githack工具处理git泄露情况 进入.git/refs目录 发现stash文件,使用notepad++打开文件 使用git dif ...
- Trollcave-suid提权
一 扫描端口 扫描开放端口:nmap -sV -sC -p- 192.168.0.149 -oA trollcave-allports 扫描敏感目录:gobuster dir -u http://19 ...
- 为什么不建议用var
看了这个例子估计你就会明白了 var a = 'global'; function test() { if (!a) { var a = 'part'; } console.log(a); } tes ...
- 视图V_160M和表T_160M的维护
今天发现一个视图,通过SM30居然无法维护,这个视图就是V_160M,表为T_160M,是采购相关的系统消息, 不过别着急,有办法维护的,呵呵,看下面: 试一试OMCQ这个事物代码吧! 分享出来,给需 ...
- PCB导线长宽与电源压降
为了计算PCB中电源线走线后的压降,需要知道PCB中使用的铜的电阻率, PCB板中的铜是直接贴上去的铜箔,因此可以当成纯铜(我问了PCB打样的厂家他们的铜的电阻率,但是他们给我说不知道,所以干脆就当成 ...