标签:beautiful blog div 价值 represent cas max ++ ade
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
题目大意:
有一个由26种宝石组成的项链,给定每一种宝石的的价值,现需要将这串项链分成两部分
如果分开的项链是一个回文的则它的价值为之一部分项链上所有宝石价值的总和,否则的话它的价值为0
求能够得到的最大价值是多少。
解题思路:
先算出这串项链的价值前缀和,然后用manachar算法求出项链的p数组,根据p数组枚举切割点,从而求得最大价值。
AC代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 using namespace std; 5 6 const int N = 500010; 7 char s[N*2]; // 项链 8 int val[26], p[N*2], sum[N]; // val存每种宝石的价值 sum存项链的价值前缀和(前i个字符价值和) 9 int pre[N], pos[N]; // pre标记前i个字符为回文串 pos标记后i个字符为回文串 10 int manachar () 11 { 12 memset(pos,0,sizeof(pos)); 13 memset(pre,0,sizeof(pre)); 14 memset(sum,0,sizeof(sum)); 15 int i, j = 0; 16 int len = strlen(s); 17 for (i = 1; i <= len; i ++) // 求项链价值的前缀和 18 sum[i] += sum[i-1]+val[s[i-1]-‘a‘]; 19 20 for (i = len; i >= 0; i --) // 预处理项链字符串 21 { 22 s[i*2+2] = s[i]; 23 s[i*2+1] = ‘#‘; 24 }s[0] = ‘@‘; 25 // puts(s); 26 27 int id = 0, mx = 0; 28 for (i = 2; s[i]; i ++) 29 { 30 p[i] = i<mx? min(p[id*2-i],mx-i) : 1; 31 while (s[i+p[i]] == s[i-p[i]]) p[i] ++; 32 if (i+p[i] > mx){ 33 id = i; 34 mx = i + p[i]; 35 } 36 if (i == p[i]) pre[p[i]-1] = 1; //表示前缀(前p[i]-1个字符)是回文串 37 if (i+p[i] == 2*len+2) pos[p[i]-1] = 1; //表示后缀(后p[i]-1个字符)是回文串 38 } 39 int ans = -0x3f3f3f3f; 40 for (i = 1; i < len; i ++) // 不断枚举切割点 求最大价值 41 { 42 j = 0; 43 if (pre[i]) j += sum[i]; 44 if (pos[len-i]) j += sum[len]-sum[i]; 45 if (j > ans) ans = j; 46 } 47 return ans; 48 } 49 int main () 50 { 51 int t,i; 52 scanf("%d",&t); 53 while (t --) 54 { 55 for (i = 0; i < 26; i ++) 56 scanf("%d",&val[i]); 57 scanf("%s",s); 58 int ans = manachar(); 59 printf("%d\n",ans); 60 } 61 return 0; 62 }
hdu 3613 Best Reward (manachar算法)
标签:beautiful blog div 价值 represent cas max ++ ade
原文地址:http://www.cnblogs.com/yoke/p/6938095.html