hdu_round3-1003.bx回文(manacher+dp)

来源:互联网 发布:淘宝品牌调性分怎么查 编辑:程序博客网 时间:2024/05/22 12:56

记录一个菜逼的成长。。

bx回文

Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 501 Accepted Submission(s): 89

Problem Description
bx有一个长度一个字符串S,bx可以对其进行若干次操作。

每次操作可以删掉一个长度为k(1 <= k <= n)的连续回文子串,bx获得ak的愉悦值。

一个字符串是回文串当且仅当正读和反读都是一样的。例如”a”,”aa”,”abcba”是回文串,”ab”,”abc”,”aabab”不是回文串。

字符串删除之后相邻的字符不会合并在一起。

现在,bx想知道他最多能获得多少愉悦值。

Input
输入第一行一个整数T,表示数据组数。

对于每组数据,第一行一个整数n。

第二行n个整数,第i个表示ai。

第三行为字符串S。

1 <= T <= 20
1 <= n <= |S| < 5000
0 <= ai < 1000000000
S只包括小写字母。

Output
对每组数据,输出bx所能获得的最大愉悦值。

Sample Input
2
3
1 2 3
aba
3
3 2 1
aba

Sample Output
3
9

manacher预处理出所有可能的回文串长度
考虑dp
dp[i]:=i
有如下转移:
以第i个字符为中心的回文串,回文串长度为len
dp[i+j]=maxdp[i+j],dp[ij1]+a[k](0jlen)
(k[ij,i+j])

ps:要对a数组进行清零,因为n!=|S|(之前没清零就一直wa

#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;#define ALL(v) (v).begin(),(v).end()#define cl(a,b) memset(a,b,sizeof(a))#define clr clear()#define pb push_back#define mp make_pair#define fi first#define se secondtypedef long long LL;typedef pair<int,int> PII;const int INF = 0x3f3f3f3f;const int maxn = 20000 + 10;char str[maxn],str1[maxn];int a[maxn],p[maxn];LL dp[maxn];void change(char s[],char s1[]){  int i,j=0;  s1[0]='!';  s1[1]='#';  for( i = 2; s[j]; i += 2 ){    s1[i] = s[j++];    s1[i+1] = '#';  }  s1[i] = '\0';}void manacher(char s1[]){  int ret = 0;  memset(p,0,sizeof(p));  int i,id=0,mx=0;  for( i = 1; s1[i]; i++ ){    if(mx>i)p[i]=min(p[2*id-i],mx-i);    else p[i]=1;    while(s1[i-p[i]]==s1[i+p[i]])        p[i]++;    if(i+p[i]>mx){        mx=i+p[i];        id=i;    }  }}int main(){  int T;scanf("%d",&T);  while(T--){    int n;    scanf("%d",&n);    cl(a,0);    for( int i = 1; i <= n; i++){      scanf("%d",a+i);    }    scanf("%s",str);    int l = strlen(str);    change(str,str1);    manacher(str1);    int len1 = strlen(str1);    cl(dp,0);    for( int i = 1; i < len1; i ++ ){      int len = p[i] - 1;      for( int j = 0; j <= len; j++ ){        dp[i+j] = max(dp[i+j],dp[i-j-1] + ( str1[i] != '#' ? a[j/2*2+1] : a[(j+1)/2*2] ) );      }     }    printf("%lld\n",dp[len1-1]);  }  return 0;}
原创粉丝点击