扩展KMP --- HDU 3613 Best Reward
Best Reward
Problem's Link: http://acm.hdu.edu.cn/showproblem.php?pid=3613
Mean:
给你一个字符串,每个字符都有一个权值(可能为负),你需要将这个字符串分成两个子串,使得这两个子串的价值之和最大。一个子串价值的计算方法:如果这个子串是回文串,那么价值就是这个子串所有字符权值之和;否则价值为0。
analyse:
扩展KMP算法运用。
总体思路:
找出所有包含第一个字母的回文串和包含最后一个字母的回文串,然后O(n)扫一遍,每次判断第i个字母之前(包含第i个字母)的子串是否是回文,以及从第i个字母后的子串是否是回文,然后计算出答案,取最大值。
具体做法:
假设输入的字符串是"abcda"
构造串s1="abcda#adcba"
求s1的Next数组,得到了包含第一个字母的回文串的位置;
构造串s2="adcba#abcda"
求s2的Next数组,得到了包含最后一个字母的回文串的位置;
用两个flag数组标记这些位置,然后扫一遍就得答案了。
中间加一个'#'并后接反串的目的是:当整个串都是回文的时候能够被Next数组记录下。
Time complexity: O(nlogn)
Source code:
第一遍写,不够优化:
- /*
- * this code is made by crazyacking
- * Time: 0MS
- * Memory: 137KB
- */
- #include <queue>
- #include <cstdio>
- #include <string>
- #include <stack>
- #include <cmath>
- #include <set>
- #include <map>
- #include <cstdlib>
- #include <climits>
- #include <vector>
- #include <iostream>
- #include <algorithm>
- #include <cstring>
- #define MAXN 500010*2
- #define LL long long
- using namespace std;
- int len;
- int Next[MAXN],ne[MAXN];
- int sum[MAXN];
- vector<int> val;
- bool flag1[MAXN],flag2[MAXN];
- char s[MAXN],s1[MAXN],s2[MAXN],sr[MAXN];
- void get_sum()
- {
- sum[]=val[s[]-'a'];
- for(int i=;i<len;++i)
- sum[i]=sum[i-]+val[s[i]-'a'];
- }
- void get_s1()
- {
- strcpy(s1,s);
- s1[len]='#';
- s1[len+]='\0';
- strcat(s1,sr);
- }
- void get_s2()
- {
- strcpy(s2,sr);
- s2[len]='#';
- s2[len+]='\0';
- strcat(s2,s);
- }
- void get_Next(char s[])
- {
- Next[]=;
- int s_len=strlen(s);
- for(int i=,k=;i<s_len;++i)
- {
- while(k!= && s[i]!=s[k])
- k=Next[k-];
- if(s[i]==s[k]) k++;
- Next[i]=k;
- }
- }
- int main()
- {
- ios_base::sync_with_stdio(false);
- cin.tie();
- int Cas;
- cin>>Cas;
- while(Cas--)
- {
- val.clear();
- int cnt=,t;
- while(cnt--)
- {
- cin>>t,val.push_back(t);
- }
- scanf("%s",s);
- len=strlen(s);
- if(strlen(s)==)
- {
- printf("%d\n",val[s[]-'a']);continue;
- }
- get_sum();
- strcpy(sr,s);
- strrev(sr);
- get_s1();
- get_s2();
- memset(flag1,,sizeof flag1);
- memset(flag2,,sizeof flag2);
- get_Next(s1);
- int k=Next[*len];
- while(k!=)
- {
- flag1[k-]=;
- k=Next[k-];
- }
- get_Next(s2);
- k=Next[*len];
- while(k!=)
- {
- flag2[k-]=;
- k=Next[k-];
- }
- reverse(flag2,flag2+len);
- long long ans=INT_MIN;
- long long tmp=;
- for(int i=;i<len-;++i)
- {
- tmp=;
- if(flag1[i])
- {
- tmp+=sum[i];
- }
- if(flag2[i+])
- {
- tmp=tmp+(sum[len-]-sum[i]);
- }
- if(tmp>ans)
- ans=tmp;
- }
- cout<<ans<<endl;
- }
- return ;
- }
- /*
- */
优化后的代码:
- /*
- * this code is made by crazyacking
- * Verdict: Accepted
- * Submission Date: 2015-05-07-16.26
- * Time: 0MS
- * Memory: 137KB
- */
- #include <queue>
- #include <cstdio>
- #include <set>
- #include <string>
- #include <stack>
- #include <cmath>
- #include <climits>
- #include <map>
- #include <cstdlib>
- #include <iostream>
- #include <vector>
- #include <algorithm>
- #include <cstring>
- #define LL long long
- #define ULL unsigned long long
- using namespace std;
- const int MAXN=;
- int val[],Next[MAXN*],sum[MAXN];
- char s[MAXN],s1[MAXN*];
- bool flag[][MAXN];
- void get_sum()
- {
- int len=strlen(s);
- sum[]=val[s[]-'a'];
- for(int i=;i<len;++i)
- sum[i]=sum[i-]+val[s[i]-'a'];
- }
- void get_Next(char ss[])
- {
- int len=strlen(ss);
- Next[]=;
- int k=;
- for(int i=;i<len;++i)
- {
- while(k!= && ss[i]!=ss[k])
- k=Next[k-];
- if(ss[i]==ss[k]) k++;
- Next[i]=k;
- }
- }
- void get_flag(int x)
- {
- strcpy(s1,s);
- int len=strlen(s);
- s1[len]='#';
- strrev(s);
- strcat(s1+len+,s);
- get_Next(s1);
- len=strlen(s1);
- int k=Next[len-];
- while(k!=)
- {
- flag[x][k-]=;
- k=Next[k-];
- }
- memset(s1,,sizeof s1);
- }
- int main()
- {
- ios_base::sync_with_stdio(false);
- cin.tie();
- int Cas;
- scanf("%d",&Cas);
- while(Cas--)
- {
- for(int i=;i<;++i)
- scanf("%d",&val[i]);
- scanf("%s",s);
- if(strlen(s)==)
- {
- printf("%d\n",val[s[]-'a']);continue;
- }
- get_sum();
- memset(flag,,sizeof flag);
- get_flag();
- get_flag();
- int len=strlen(s);
- reverse(flag[],flag[]+len);
- long long ans=LLONG_MIN,tmp;
- for(int i=;i<len-;++i)
- {
- tmp=;
- tmp=(flag[][i]?sum[i]:)+(flag[][i+]?sum[len-]-sum[i]:);
- ans=ans>tmp?ans:tmp;
- }
- printf("%lld\n",ans);
- }
- return ;
- }
- /*
- */
扩展KMP --- HDU 3613 Best Reward的更多相关文章
- HDU 3613 Best Reward 正反两次扩展KMP
题目来源:HDU 3613 Best Reward 题意:每一个字母相应一个权值 将给你的字符串分成两部分 假设一部分是回文 这部分的值就是每一个字母的权值之和 求一种分法使得2部分的和最大 思路:考 ...
- HDU 3613 Best Reward(扩展KMP求前后缀回文串)
题目链接: 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"(Manacher算法)
传送门 题意: 国王为了犒劳立下战功的大将军Li,决定奖给Li一串项链,这个项链一共包含26中珠子"a~z",每种珠子都有 相应的价值(-100~100),当某个项链可以构成回文时 ...
- 扩展KMP - HDU 4333 Revolving Digits
Revolving Digits Problem's Link Mean: 给你一个字符串,你可以将该字符串的任意长度后缀截取下来然后接到最前面,让你统计所有新串中有多少种字典序小于.等于.大于原串. ...
- HDU 3613 Best Reward(扩展KMP)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=3613 [题目大意] 一个字符串的价值定义为,当它是一个回文串的时候,价值为每个字符的价值的和,如果 ...
- 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算法求解一个串的前、后缀回文串标记数组)
题目链接: https://cn.vjudge.net/problem/HDU-3613 After an uphill battle, General Li won a great victory. ...
- HDU 3613 Best Reward ( 拓展KMP求回文串 || Manacher )
题意 : 给个字符串S,要把S分成两段T1,T2,每个字母都有一个对应的价值,如果T1,T2是回文串,那么他们就会有一个价值,这个价值是这个串的所有字母价值之和,如果不是回文串,那么这串价值就为0.问 ...
随机推荐
- CentOS 伪装安装TSA for DB2
DB2 HADR需要额外安装TSA,正常情况下CentOS无法通过安装前验证.会报一个说发行版不支持的错误. 可以通过伪装成RHEL的方式使得正常安装. 修改方式如下 修改/etc/system-re ...
- 【C】——幻方算法
一.幻方按照阶数可分成了三类,即奇数阶幻方.双偶阶幻方.单偶阶幻方. 二.奇数阶幻方(劳伯法) 奇数阶幻方最经典的填法是罗伯法.填写的方法是: 把1(或最小的数)放在第一行正中:按以下规律排列剩下的( ...
- 给The Lab Renderer for Unity中地形添加阴影
The Lab Renderer for Unity是Valve针对VR在Unity的体验渲染器,提高VR的渲染效率,更多的大家可以查相应资料,在这,说个The Lab Renderer for Un ...
- [AX2012 R3]关于Named user license report
Named user license报表是用来统计各种授权类型用户数的,这里来看看报表数据具体是如何来的.这是一个SSRS的报表,最主要的数据源是来自于类SysUserLicenseCountRepo ...
- Windows 8.1 Preview 开发资源汇总
Microsoft Build 2013开发者大会已经结束,从Session安排上看主要以Windows 8.1为主.我相信大家有已经或多或少的体验过Windows 8.1 Preview了,关于操作 ...
- 【转】--在Android源码树中添加userspace I2C读写工具(i2c-util)
通过/dev/i2c-n节点,用户可以在userspace直接访问板上的i2c外设寄存器,主要是透过I2C_RDWR这个IO控制命令将i2c_msg数组传递给kernel去执行.下面的代码可以完成这个 ...
- 锁屏上显示Activity
在Android中,有些比较强的提醒,需要用户紧急处理的内容.需要唤醒屏幕,甚至在锁定屏幕的情况下,也要显示出来.例如,来电界面和闹钟提醒界面.这是怎样实现的呢? 其实,实现起来非常简单.只要给Act ...
- mysql int(1) 与 tinyint(1) 有什么区别?
From: http://www.cnblogs.com/xiaochaohuashengmi/archive/2011/08/25/2153016.html mysql int(1) tinyint ...
- make no mistake, we are the last line of defense.
make no mistake, we are the last line of defense.
- js webapp 滑动事件
var startX, startY, endX, endY; $(".detailImg").on("touchstart", touchStart);$(& ...