• [Manacher][HDU3613][Best Reward]


    题意:
    将一段字符串 分割成两个串
    如果分割后的串为回文串,则该串的价值为所有字符的权值之和(字符的权值可能为负数),否则为0。
    问如何分割,使得两个串权值之和最大

    思路:
    裸的:
    枚举分割点,计算,O(n) 判断是否回文
    总复杂度O(n^2)
    优化:
    利用Manacher的预处理 O(1)判断是否回文
    复杂度O(n)

    //Manacher
    /*  
    ** 求最长回文子串 
    */ 
    #include <cstdio>
    #include <cstring> 
    #include <iostream>
    #include <cstdlib>
    using namespace std;
    const int MAXN=550000;
    char Ma[MAXN*2];
    int Mp[MAXN*2];
    void Manacher(char s[],int len){
        int l=0;
        Ma[l++]='$';
        Ma[l++]='#';
        for(int i=0;i<len;i++){
            Ma[l++]=s[i];
            Ma[l++]='#';
        } 
        Ma[l]=0;
        int mx=0,id=0;
        for(int i=0;i<l;i++){
            Mp[i]=mx>i?min(Mp[2*id-i],mx-i):1;
            while(Ma[i+Mp[i]]==Ma[i-Mp[i]]) Mp[i]++;
            if(i+Mp[i]>mx){
                mx=i+Mp[i];
                id=i;
            } 
        }
    } 
    /*
     * abaaba
     * i:              0 1  2  3  4  5  6  7  8  9 10 11 12 13
     *Ma[i]:           $ #  a  #  b  #  a  #  a  # b  #  a  #  
     *Mp[i]:           1 1  2  1  4  1  2  7  2  1 4  1  2  1
     */
    char s[MAXN];
    int sum[MAXN*2];
    int v[30];
    void input()
    {
        for(int i=1;i<=26;i++)
        scanf("%d",&v[i]);
        scanf("%s",s);
    }
    void get_sum()
    {
        int len=strlen(Ma);
        for(int i=1;i<len;i++)
        {
            sum[i]=sum[i-1];
            if('a'<=Ma[i]&&Ma[i]<='z')
            sum[i]+=v[Ma[i]-'a'+1];
    //      printf("%d %d
    ",i,sum[i]);
        }
    }
    void solve()
    {
        int len=strlen(s);
        Manacher(s,len);
        get_sum();
        len=strlen(Ma);
        int ans=-0x3f3f3f3f;
        for(int i=3;i<len-1;i=i+2)
        {
            int a1=0,a2=0;
            //判断之前的串是不是回文串
            if((((2+(i-1))/2)+Mp[(2+(i-1))/2]-1)>=(i-1))
            a1=sum[i]-sum[1];
            if(((len+i-1)/2-Mp[(len+i-1)/2]+1)<=(i+1))
            a2=sum[len-2]-sum[i];
            if(ans<a1+a2)
            ans=a1+a2;
        }
        cout<<ans<<endl;
    }
    int main()
    {
    //  freopen("a.in","r",stdin);
        int T;
        cin>>T;
        while(T--)
        {
            input();
            solve();
        }
    }
  • 相关阅读:
    Linux cat
    Linux touch
    Win10 UAP 绑定
    Win10 资源文件
    Win10 启动模拟器
    Win10 安装Vs2015 社区版和企业版各个问题汇总
    Win10 开发者模式开启
    android 入门-本地化语言
    android 入门-基础了解
    wp8 入门到精通 定时更新瓷贴
  • 原文地址:https://www.cnblogs.com/zy691357966/p/5480314.html
Copyright © 2020-2023  润新知