zoukankan      html  css  js  c++  java
  • HDU 3613 Best Reward(manacher求前、后缀回文串)

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

    题目大意:

    题目大意就是将字符串s分成两部分子串,
    若子串是回文串则需计算价值,否则价值为0,求分割字符串s能获得的最大价值。

    解题思路:

    用manacher算法计算出p[i],每次计算p[i]是顺便计算一下这段回文串
    是否能到达边界,若能则计算出前缀或者后缀的结束位置,标记起来。//还有之前数组开1e6+5教C++是错的,改成2e6+5就对了,不觉明历。。。。

    代码(复杂点的)

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 const int N=2e6+5;
     7 const int INF=0x3f3f3f3f;
     8 
     9 int len1,len2;
    10 int p[N],sum[N],val[N],pre[N],hou[N];
    11 char s[N],str[N];
    12 
    13 void init(){
    14     str[0]='$';
    15     str[1]='#';
    16     for(int i=0;i<len1;i++){
    17         str[i*2+2]=s[i];
    18         str[i*2+3]='#';
    19     }
    20     len2=len1*2+2;
    21     str[len2]='';
    22 }
    23 
    24 void manacher(){
    25     int id=0,mx=0;
    26     for(int i=1;i<len2;i++){
    27         if(mx>i) p[i]=min(p[2*id-i],mx-i);
    28         else p[i]=1;
    29         while(str[i+p[i]]==str[i-p[i]])
    30             p[i]++;
    31         if(p[i]+i>mx){
    32             id=i;
    33             mx=p[i]+i;
    34         }
    35         if(i-p[i]==0){
    36             pre[p[i]+i-1]=1;
    37         }
    38         if(i+p[i]==len2){
    39             hou[i-p[i]+1]=1;
    40         }
    41     }
    42 }
    43 
    44 
    45 int main(){
    46     int t;
    47     scanf("%d",&t);
    48     while(t--){
    49         memset(pre,0,sizeof(pre));
    50         memset(hou,0,sizeof(hou));
    51         for(int i=0;i<26;i++){
    52             scanf("%d",&val[i]);
    53         }
    54         scanf("%s",s);
    55         len1=strlen(s);
    56         init();
    57         manacher();
    58         for(int i=1;i<len2;i++){
    59             if(i=='#') sum[i]=sum[i-1];
    60             else sum[i]=sum[i-1]+val[str[i]-'a'];
    61         }
    62         int ans=-INF;
    63         //枚举分割点
    64         for(int i=2;i<len2-1;i++){
    65             int tmp=0;
    66             if(pre[i]) tmp+=sum[i];
    67             if(hou[i]) tmp+=sum[len2-1]-sum[i];
    68             ans=max(ans,tmp);
    69         }
    70         printf("%d
    ",ans);
    71     }
    72     return 0;
    73 }

     简略了一点的

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 const int N=2e6+5;
     7 const int INF=0x3f3f3f3f;
     8 
     9 int len1,len2;
    10 int p[N],sum[N],val[N];
    11 char s[N],str[N];
    12 
    13 void init(){
    14     str[0]='$';
    15     str[1]='#';
    16     for(int i=0;i<len1;i++){
    17         str[i*2+2]=s[i];
    18         str[i*2+3]='#';
    19     }
    20     len2=len1*2+2;
    21     str[len2]='@';
    22 }
    23 
    24 void manacher(){
    25     int id=0,mx=0;
    26     for(int i=1;i<len2;i++){
    27         if(mx>i) p[i]=min(p[2*id-i],mx-i);
    28         else p[i]=1;
    29         while(str[i+p[i]]==str[i-p[i]])
    30             p[i]++;
    31         if(p[i]+i>mx){
    32             id=i;
    33             mx=p[i]+i;
    34         }
    35     }
    36 }
    37 
    38 
    39 int main(){
    40     int t;
    41     scanf("%d",&t);
    42     while(t--){
    43         for(int i=0;i<26;i++){
    44             scanf("%d",&val[i]);
    45         }
    46         scanf("%s",s);
    47         len1=strlen(s);
    48         init();
    49         manacher();
    50         for(int i=1;i<len2;i++){
    51             if(i=='#') sum[i]=sum[i-1];
    52             else sum[i]=sum[i-1]+val[str[i]-'a'];
    53         }
    54         int ans=-INF;
    55         //枚举分割点
    56         for(int i=0;i<len1-1;i++){
    57             int tmp=0,mid;
    58             mid=((i+1)*2+1+1)/2;
    59             if(mid-p[mid]==0) tmp+=sum[(i+1)*2];
    60             mid=((i+2)*2-1+len1*2+1)/2;
    61             if(mid+p[mid]==len2) tmp+=sum[len2-1]-sum[(i+2)*2-1];
    62             ans=max(tmp,ans);
    63         }
    64         printf("%d
    ",ans);
    65     }
    66     return 0;
    67 }
  • 相关阅读:
    hibernate 4 需要导入的jar包
    中国象棋马走日(要求打印每一种走法) — 递归
    最长公共子串
    国际象棋马走日(骑士周游)
    八皇后
    约瑟夫问题
    hashtable的运用实例
    用较小的代价去除字符串中的空格
    C++ string数据类型的实现
    strcpy、strncpy与memcpy的区别与使用方法
  • 原文地址:https://www.cnblogs.com/fu3638/p/8503573.html
Copyright © 2011-2022 走看看