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 }
原文地址:https://www.cnblogs.com/fu3638/p/8503573.html