zoukankan      html  css  js  c++  java
  • HDU 3613 Best Reward(扩展KMP)

     

    【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=3613

    【题目大意】 

      一个字符串的价值定义为,当它是一个回文串的时候,价值为每个字符的价值的和,如果不是回文串,价值为0,现在给出每种字符的价值。给出一个字符串,要求将其划分为两个子串,要求两个子串的价值和最大。

    【题解】 

      求出字符串S的反串T,以T为模板跑一遍S的exkmp就能得到S的后缀是否为回文串的信息,同理以S为模板跑一遍T就可以得到S的前缀是否是回文串的信息,枚举每个断点,取最大值即可。

     

    【代码】 

    #include <cstdio>
    #include <cstring> 
    using namespace std;
    const int N=500010;
    int len,LCP[N],ex1[N],ex2[N],a[N],s[N];
    char S[N],T[N];
    void getLCP(char *T){
        int i,len=strlen(T);
        LCP[0]=len;
        for(i=0;i<len-1&&T[i]==T[i+1];i++);
        LCP[1]=i; int a=1;
        for(int k=2;k<len;k++){
            int p=a+LCP[a]-1,L=LCP[k-a];
            if((k-1)+L>=p){
                int j=(p-k+1)>0?(p-k+1):0; 
                while(k+j<len&&T[k+j]==T[j])j++;
                LCP[k]=j,a=k;
            }else LCP[k]=L;
        } 
    }
    void exkmp(char *S,char *T,int *extend){
        memset(LCP,0,sizeof(LCP)); 
        getLCP(T); 
        int Slen=strlen(S),Tlen=strlen(T),a=0;
        int MinLen=Slen>Tlen?Tlen:Slen;
        while(a<MinLen&&S[a]==T[a])a++;
        extend[0]=a,a=0;
        for(int k=1;k<Slen;k++){
            int p=a+extend[a]-1,L=LCP[k-a];  
            if((k-1)+L>=p){
               int j=(p-k+1)>0?(p-k+1):0; 
               while(k+j<Slen&&j<Tlen&&S[k+j]==T[j])j++; 
               extend[k]=j;a=k; 
            }else extend[k]=L;         
        }
    }
    void revcpy(char* S,char* T,int len){ 
        memset(T,0,sizeof(T)); 
        for(int i=0,k=len-1;i<len;++i,--k)T[i]=S[k]; 
    }int Cas;
    int main(){
        scanf("%d",&Cas);
        while(Cas--){
            for(int i=0;i<26;i++)scanf("%d",&a[i]);
            scanf("%s",S);len=strlen(S);
            for(int i=0;S[i];i++)s[i+1]=s[i]+a[S[i]-'a'];
            revcpy(S,T,len);
            exkmp(S,T,ex2); 
            exkmp(T,S,ex1);
            int ans=-1e9;
            for(int i=0;i<len;i++){
                if(i&&ex1[i]+i==len){
                    int j=ex1[i],tmp=s[j];
                    if(ex2[j]+j==len)tmp+=s[len]-s[j];
                    if(tmp>ans)ans=tmp;
                }else{
                    int j=i+1,tmp=0;
                    if(ex2[j]+j==len)tmp+=s[len]-s[j];
                    if(tmp>ans)ans=tmp;
                }
            }printf("%d
    ",ans);
        }return 0;
    }
    

     

  • 相关阅读:
    angular ng-bind-html异常Attempting to use an unsafe value in a safe context处理
    JS执行机制详解,定时器时间间隔的真正含义
    es6入门4--promise详解
    es6入门3--箭头函数与形参等属性的拓展
    JS判断滚动条到底部,页面是否有滚动条
    js forEach跳出循环
    es6入门2--对象解构赋值
    前端开发与日常好玩的的小工具,网站与插件分享
    详解 线程池
    详解 volatile关键字 与 CAS算法
  • 原文地址:https://www.cnblogs.com/forever97/p/hdu3613.html
Copyright © 2011-2022 走看看