您的位置:首页 > 其它

hdu 3613 Manacher+枚举+前缀和打表

2018-01-26 13:15 169 查看
点击打开链接
//马拉车算法+枚举切割点+打表储存(前缀和)
//manacher算法求最长回文子串,时间复杂度为O(n),基本思想是充分利用已求得的回文串长度
//关键是构造P数组
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=5*1e5+10;
int P[maxn<<1];
char T1[maxn];
char T2[maxn<<1];
int sum[maxn];
int num[30];
//P[i]-1恰好是位置i处的最长回文子串长度
//求解P数组
void Manacher(char T[])
{
int pos=0,mx=0;             //mx为当前可以触及的最远位置,pos为这种状态时的对称轴位置
P[0]=0;                 //0位置不考虑,为$标志
for(int i=1;T[i];i++)
{
if(mx>i) P[i]=min(P[2*pos-i],mx-i);         //第一种情况:i在mx左侧,在左侧时又有两种情况:
//两种情况:1.i关于pos的j的回文串较短 2.i关于pos的j的回文串较长,分别对应min中的两个值
else P[i]=1;                    //i在mx右侧的情况
while(T[i+P[i]]==T[i-P[i]]) P[i]++;                 //进行匹配
if(mx<P[i]+i)                   //更新mx值和pos值
{
mx=P[i]+i;
pos=i;
}
}
}
void getsum()
{
sum[0]=num[T1[0]-'a'];
int f=strlen(T1);
for(int i=1;i<f;i++)
sum[i]=sum[i-1]+num[T1[i]-'a'];
}
// 构造T2串
//解决长度奇偶性带来的对称轴位置问题:在所有的空隙位置(包括首尾)插入一种原串中没有的符号,这样,奇数加偶数必为奇数
void init()
{
scanf("%s",T1);
int i,j=2;
T2[0]='$',T2[1]='#';                //$符号是为了防止数组下标越界
for(i=0;T1[i];i++)
{
T2[j++]=T1[i];
T2[j++]='#';
}
T2[j]='\0';
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(sum,0,sizeof(sum));
memset(num,0,sizeof(num));
int mi=0;
for(int i=0;i<26;i++)
scanf("%d",&num[i]);
init();
getsum();
Manacher(T2);
//枚举切割点
int f=strlen(T1);
for(int i=0;i<f-1;i++)
{
//先左串,后右串
int temp=0;
int k1=i+1,k2=f-i-1;
int k=P[i+2]-1;
if(k==k1) temp+=sum[i];
k=P[i+f+2]-1;
if(k==k2) temp+=sum[f-1]-sum[i];
mi=max(mi,temp);
}
printf("%d\n",mi);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息