hdu 3613 Best Reward回文子串Manocher算法




Problem Description
After an uphill battle, General Li won a great victory. Now the head of state decide to reward him with honor and treasures for his great exploit.

One of these treasures is a necklace made up of 26 different kinds of gemstones, and the length of the necklace is n. (That is to say: n gemstones are stringed together to constitute this necklace, and each of these gemstones belongs to only one of the 26 kinds.)

In accordance with the classical view, a necklace is valuable if and only if it is a palindrome - the necklace looks the same in either direction. However, the necklace we mentioned above may not a palindrome at the beginning. So the head of state decide to cut the necklace into two part, and then give both of them to General Li.

All gemstones of the same kind has the same value (may be positive or negative because of their quality - some kinds are beautiful while some others may looks just like normal stones). A necklace that is palindrom has value equal to the sum of its gemstones' value. while a necklace that is not palindrom has value zero.

Now the problem is: how to cut the given necklace so that the sum of the two necklaces's value is greatest. Output this value.

 

Input
The first line of input is a single integer T (1 ≤ T ≤ 10) - the number of test cases. The description of these test cases follows.

For each test case, the first line is 26 integers: v 1, v 2, ..., v 26 (-100 ≤ v i ≤ 100, 1 ≤ i ≤ 26), represent the value of gemstones of each kind.

The second line of each test case is a string made up of charactor 'a' to 'z'. representing the necklace. Different charactor representing different kinds of gemstones, and the value of 'a' is v 1, the value of 'b' is v 2, ..., and so on. The length of the string is no more than 500000.

 

Output
Output a single Integer: the maximum value General Li can get from the necklace.
 

Sample Input
  
  
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 acacac
 

Sample Output
  
  
1 6






题目意思:给一个字符串,分成两份,如果某一份是回文串,得到的值就是所有字符的和,否则为0

前26个数字给的是每个字母的价值

求一种分割使得得到的值最大

枚举分割点,如果左右两边有回文串就加上它的值,然后去最大值即可


如何求回文串:

Manocher算法是o(n)的算法求回文串的。求法跟扩展kmp类似,其实可以看成是用同一理念的方法

因为回文串分奇数和偶数,为了避免这个麻烦,可以在每个字符中间加一个不会出现的字符,于是每个回文串要么

以新加的字符为中心,要么以原来的字符问中心,以原来的字符为中心的就是原串中的奇数回文子串,以新字符为中心的

就是原串中的偶数子串


方法:

跟扩展kmp一样,用一个指针t,表示以t为中心的回文串,在所有遍历过的回文串中能访问到最远的(表示t+common[t])最大,

那么在t+common[t]之前所有的字符都被访问过了。

现在遇到i这个中心,根据回文串的对称性,就知道i关于t对称点的回文长度,如果这个长度+i不超过t+common[t]那么i的回文长度就

已经知道了,如果>=了,因为t+common[t]以右的字符都未被访问过,所以需要继续查看,然后跟新t,

和扩展kmp一样的性质。。。



#include<cstdio>
#include<cstring>
#define max(a,b) a>b?a:b
#define min(a,b) a<b?a:b
#define maxn 1000007
int common[maxn];
void Manocher(char *word,int len){
    common[0] = 1;
    int p = 0,t=1,k,f;
    for(int i = 1;i < len; i++){
        f = (p<<1)-i;
        k = common[f];
        if(k+i < t) common[i] = k;
        else {
            k = min(k,t-i);
            while(word[i+k]==word[i-k]&&i+k<len&&i>=k)k++;
            common[i] = k;
            p=i;
            t=i+k;
        }
    }
}
char word[maxn];
int value[200];
int sum[maxn>>1];
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        for(int i = 0;i < 26;i++)
            scanf("%d",&value['a'+i]);
            getchar();
        gets(word);
        int len = strlen(word);
        sum[0] = value[word[0]];
        for(int i = 1;i < len; i++)
            sum[i] = value[word[i]]+sum[i-1];
        for(int i = len-1;i>0;i--)
            word[i<<1] = word[i],word[(i<<1)-1]=' ';
        Manocher(word,len*2-1);
        int ans = 0,res;
        for(int i = 0;i < len-1;i++){
            res= 0;
            if(common[i] == i+1)res=sum[i];
            if(common[len+i] == len-i-1)res+=sum[len-1]-sum[i];
            ans = max(ans,res);
        }
        printf("%d\n",ans);
    }
    return 0;
}






















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GDRetop

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值