HDU 3613 Best Reward(扩展kmp)
来源:互联网 发布:mac怎么转换音频格式 编辑:程序博客网 时间:2024/04/30 04:27
Description
给出一个只由小写字母组成的字符串以及每个小写字母的价值,现要将这个字符串分成两半,如果某一半是回文串则将累加这一半串的价值(价值即为这个串中每个字符的价值之和),问能得到的最大价值
Input
第一行为一整数T表示用例组数,每组用例首先输入26个整数表示a到z这26个小写字母的价值,之后输入长度不超过500000的一个字符串
Output
对于每组用例,输出将该字符串分成两半后能得到的最大价值
Sample Input
2
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
aba
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
acacac
Sample Output
1
6
Solution
问题在于如果快速判断a串的前缀和后缀是否是回文串,这里只说前缀(因为后缀就是反串的前缀),考虑串a与其反串b的匹配,如果a的某个前缀是回文串,那么因为其反串是b串的一个后缀,所以只要extend[i]=len-i,那么前缀a[0~i]就是一个回文串,同理,在b与a的匹配中,如果extend[i]=len-i,那么后缀a[len-1-i,len-1]就是一个回文串,做两边扩展kmp通过extend数组可以得到以第i个字符结尾或者开始的前后缀是否为回文串,之后O(n)枚举切割点更新最大价值即可(需要预处理出价值前缀和)
Code
#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>using namespace std;#define maxn 555555char a[maxn],b[maxn];int T,v[33],sum[maxn],flag1[maxn],flag2[maxn],nex[maxn],extend[maxn];void extend_kmp(char *a,char *b) { int i,j,k,la=strlen(a),lb=strlen(b); for(i=0;i+1<la&&a[i+1]==a[i];i++); nex[1]=i; k=1; for(i=2;i<la;i++) { int len=k+nex[k]; nex[i]=min(nex[i-k],max(0,len-i)); while(i+nex[i]<la&&a[nex[i]]==a[i+nex[i]])nex[i]++; if(i+nex[i]>k+nex[k])k=i; } for(i=0;i<la&&i<lb&&a[i]==b[i];i++); extend[0]=i; k=0; for(i=1;i<lb;i++) { int len=k+extend[k]; extend[i]=min(nex[i-k],max(0,len-i)); while(i+extend[i]<la&&i+extend[i]<lb&&a[extend[i]]==b[extend[i]+i]) extend[i]++; if(k+extend[k]<i+extend[i])k=i; }}int main(){ scanf("%d",&T); while(T--) { memset(flag1,0,sizeof(flag1)); memset(flag2,0,sizeof(flag2)); for(int i=0;i<26;i++)scanf("%d",&v[i]); scanf("%s",a); int len=strlen(a); for(int i=0;i<len;i++)b[i]=a[len-1-i]; sum[0]=v[a[0]-'a']; for(int i=0;i<len;i++)sum[i]=sum[i-1]+v[a[i]-'a']; extend_kmp(a,b); for(int i=0;i<len;i++)if(extend[i]==len-i)flag1[len-1-i]=1; extend_kmp(b,a); for(int i=0;i<len;i++)if(extend[i]==len-i)flag2[i]=1; int ans=v[a[0]-'a']; for(int i=0;i<len-1;i++) { int temp=flag1[i]*sum[i]+flag2[i+1]*(sum[len-1]-sum[i]); ans=max(ans,temp); } printf("%d\n",ans); } return 0;}
0 0
- HDU 3613 Best Reward(扩展kmp)
- hdu 3613 Best Reward (扩展KMP)
- HDU 3613Best Reward(扩展KMP解法)
- hdu 3613 Best Reward 扩展kmp
- hdu 3613 Best Reward (kmp扩展)
- HDU 3613 Best Reward(扩展KMP)
- 扩展KMP --- HDU 3613 Best Reward
- HDU 3613 Best Reward(扩展KMP模板)
- KMP hdu-3613-Best Reward
- HDU 3613 Best Reward(扩展KMP:回文判断)
- HDU 3613 Best Reward 正反两次扩展KMP
- 扩展kmp入门---hd Best Reward 3613
- HDU3613 Best Reward(扩展KMP)
- HDU 3613 Best Reward(扩展KMP的应用:回文串判断+扩展KMP模板)
- HDU 3613 Best Reward(KMP+思维||manacher算法)
- HDU 3613 Best Reward ---- 拓展KMP
- Best Reward (hdu 3613 拓展KMP)
- HDU 3613 Best Reward manacher || kmp || extkmp
- Win10 Bash初体验
- tomcat配置文件server.xml详解
- PHP截取中英文字符串
- AndroidStudio2.0配置NDK
- 每天一个linux命令(30): chown命令
- HDU 3613 Best Reward(扩展kmp)
- 使用__slots__
- Mysql几种索引类型的区别及适用情况
- 初学者对于结构体内存对齐与补齐的理解
- RAID磁盘利用率详解
- 使用vmware玩openwrt
- rtsp与sip的不同
- nyoj_63 小猴子下落
- 判断一个单链表是否有环