码迷,mamicode.com
首页 > 其他好文 > 详细

Best Reward HDU 3613(回文子串Manacher)

时间:2015-08-21 14:58:43      阅读:152      评论:0      收藏:0      [点我收藏+]

标签:

题目大意:有一个串(全部由小写字母组成),现在要把它分成两部分,如果分开后的部分是回文串就计算出来它的价值总和,如果不是回文的那么价值就是0,最多能得到的最大价值。
 
分析:首先的明白这个最大价值有可能是负数,比如下面:
-1 -1 -1.....
aaa
这样的情况不管怎么分,分出来的串都是回文串,所以得到的最大价值是 -3。
求回文串的算法使用的是Manacher算法,线性的复杂度。
 
代码如下:
================================================================================================================
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

const int MAXN = 1e6+7;
const int MAXM = 1007;
const int oo = 1e9+7;
char str[MAXN];
int p[MAXN], val[27], sum[MAXN];
bool Left[MAXN], Right[MAXN];

/**
str[]   先存原字符串,后存扩展后的字符串
p[]     p[i] 表示以i为中心的回文串有多长(只记录一边的长度)、
sum[]   sum[i]表示前i个字符的总价值和
Left[]  Left[i] 表示前缀长度为 i 的串是否是回文串
Right[] Right[i]  表示后缀长度为 i 的串是否是回文串
**/

void Manacher(char str[], int N)
{
    int i, id=0;

    for(i=2; i<N; i++)
    {
        if(p[id]+id > i)
            p[i] = min( p[id*2-i], p[id]+id-i);
        else p[i] = 1;

        while(str[ i+p[i] ] == str[ i-p[i] ])
            p[i]++;

        if(p[id]+id < p[i]+i)
            id = i;

        if(p[i] == i)
            Left[p[i]-1] = true;
        if(p[i]+i-1 == N)
            Right[p[i]-1] = true;
    }
}

int main()
{
    int T;

    scanf("%d", &T);

    while(T--)
    {
        int i;

        memset(Left, false, sizeof(Left));
        memset(Right, false, sizeof(Right));
        memset(p, false, sizeof(p));

        for(i=0; i<26; i++)
            scanf("%d", &val[i]);

        scanf("%s", str);

        int len = strlen(str);

        for(i=1; i<=len; i++)
            sum[i] = sum[i-1]+val[str[i-1]-a];

        for(i=len; i>=0; i--)
        {
            str[i+i+2] = str[i];
            str[i+i+1] = #;
        }
        str[0] = $;

        Manacher(str, len+len+1);

        int ans = -oo;

        for(i=1; i<len; i++)
        {
            int temp = 0;

            if(Left[i] == true)
                temp += sum[i];
            if(Right[len-i] == true)
                temp += sum[len]-sum[i];

            ans = max(ans, temp);
        }

        printf("%d\n", ans);
    }

    return 0;
}

 

Best Reward HDU 3613(回文子串Manacher)

标签:

原文地址:http://www.cnblogs.com/liuxin13/p/4747537.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!