hdu3613(Manacher)

来源:互联网 发布:微信转换淘宝链接 编辑:程序博客网 时间:2024/05/18 07:13

链接:点击打开链接

题意:给出二十六个字母每一个字母的权值,现给个字符串,要求将这个字符串分成两部分,只有当分成后的字符串是回文时,才能计算其字母的权值和,问怎么分使得权值和最大

#include <queue>#include <vector>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;const int siz=500005;int n,val[30];int lr[siz<<1],sum[siz];char s[siz],str[siz<<1];void manancher(){    int i,ma,pos;    ma=pos=0;    for(i=0;i<n;i++){        if(i<ma)        lr[i]=min(lr[2*pos-i],ma-i);        else        lr[i]=1;        while(str[i-lr[i]]==str[i+lr[i]]){            if((i-lr[i]<0)||(i+lr[i]>=n))            break;            lr[i]++;        }        if(i+lr[i]>ma){            ma=i+lr[i];            pos=i;        }    }}                                               //manacher模板int main(){    int t,i,j,ans,len,tmp;    scanf("%d",&t);    while(t--){        for(i=0;i<26;i++)        scanf("%d",&val[i]);        scanf("%s",s);        sum[0]=val[s[0]-'a'];        for(i=1;s[i];i++)        sum[i]=sum[i-1]+val[s[i]-'a'];        n=0;        str[n++]='#';        for(i=0;s[i];i++)        str[n++]=s[i],str[n++]='#';        manancher();        len=strlen(s);        if(len==2){            printf("%d\n",val[s[0]-'a']+val[s[1]-'a']);            continue;        }        ans=0;        for(i=2;i<=n-3;i+=2){               `   //就是枚举#的位置,然后推出前后回文的            tmp=0;                              //的中心,再根据前缀和计算,画一画就出来了            if(lr[i/2]-1==i/2)            tmp+=sum[i/2-1];            if(lr[i+(n-1-i)/2]-1==(n-1-i)/2)            tmp+=(sum[len-1]-sum[i/2-1]);            ans=max(ans,tmp);        }        printf("%d\n",ans);    }    return 0;}

代码: