标签:one 重叠 include int const tor for different ade
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 acacacSample Output
1 6
题意是给出26个字母的value,然后给出一个字符串,把字符串分成两段,每段不为空,如果是回文就是各个字符value和,如果不是则为0,求最大的sumval。
代码:
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; char s[1000005];//s是字符串,之所以是最大大小的两倍是因为思路用到了回文的特性,反转后相等,借助kmp,在s后面加上原串的反转,可以找出回文串 int nexti[1000005],sum[500001];///nexti记录长度为i的字符串中前缀和后缀重叠的最大大小,sum记录前缀和 int val[26],n,sumval[500001] = {0};//val记录26个字母的value,sumval记录某个位置划分的前缀value void getnexti()//确立nexti { nexti[0] = -1; int k = -1,i = 0; while(i < (n << 1)) { if(k == -1 || s[i] == s[k])nexti[++ i] = ++ k; else k = nexti[k]; } } void check(int k) { sum[0] = 0; for(int i = 0;i < n;i ++) sum[i + 1] = sum[i] + val[s[i] - ‘a‘]; reverse_copy(s,s+n,s+n);///反转添加到s后,然后kmp getnexti(); int p = n << 1; if(k == 0)///原串求前缀 { while(p != 0) { if(p < n)sumval[p] += sum[p]; p = nexti[p]; } } else///原串进行反转,相当于求后缀,把同一位置的前缀和后缀和加到一块就好了,然后求最大值 { int ans = 0; while(p != 0) { if(p < n) { sumval[n - p] += sum[p]; ans = max(ans,sumval[n - p]); } p = nexti[p]; } cout<<ans<<endl; } } int main() { int T; cin>>T; while(T --) { for(int i = 0;i < 26;i ++) cin>>val[i]; cin>>s; n = strlen(s); memset(sumval,0,sizeof(int)*n);///之前一直wa,因为这里没有清0 check(0); reverse(s,s+n); check(1); } }
标签:one 重叠 include int const tor for different ade
原文地址:http://www.cnblogs.com/8023spz/p/7786831.html