标签:
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3613
题意就是给你一个串s 然后求把s分成两部分之后的价值总和是多少,分开的串 如果是回文那么价值就是每个字母的价值之和,如果不是那么价值就是0;
例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
abbadf
那么可以分成abba 和df abba的价值是1+2+2+1=6,df不是回文串所以价值为0;总价值就是6;
我们可以用数组L【i】R【i】来记录串的前缀长度为i的是否是回文串和后缀长度为i的是否是回文串;
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; const int N = 1e6+7; int v[26], sum[N], p[N]; ///sum[i]代表s串中前i个字符的价值总和; ///p[i]代表以i为中心的回文串的半径(包含i本身); char s[N]; bool L[N], R[N]; ///L[i]表示前i个字符是否是回文串,R[i]表示长度为i的后缀是否为回文串; void Manacher(char s[], int n) { int Id = 0, mx = 0; for(int i=2; i<n; i++) { if(mx>i) p[i] = min(mx-i, p[Id*2-i]); else p[i] = 1; while(s[i+p[i]] == s[i-p[i]]) p[i]++; if(mx < p[i]+i) { mx = p[i]+i; Id = i; } if(p[i] == i) L[p[i]-1] = true; if(p[i]+i == n) R[p[i]-1] = true; } } int main() { int T; scanf("%d", &T); while(T--) { memset(L, 0, sizeof(L)); memset(R, 0, sizeof(R)); memset(p, 0, sizeof(p)); memset(sum, 0, sizeof(sum)); for(int i=0; i<26; i++) scanf("%d", &v[i]); scanf("%s", s); int len = strlen(s); for(int i=1; i<=len; i++) sum[i] += sum[i-1] + v[s[i-1]-‘a‘]; for(int i=len; i>=0; i--) { s[i+i+2] = s[i]; s[i+i+1] = ‘#‘; } s[0]=‘$‘; Manacher(s, 2*len+2); int ans = 0; for(int i=1; i<len; i++) { int t=0; if(L[i]) t+=sum[i]; if(R[len-i]) t+=sum[len]-sum[i]; ans = max(ans, t); } printf("%d\n", ans); } return 0; }
Best Reward---hdu3613(manacher 回文串)
标签:
原文地址:http://www.cnblogs.com/zhengguiping--9876/p/4851179.html